我创建了一个Angular 7手风琴组件SlackBlitz Example:
export class AccordionComponent {
@ContentChildren(PanelComponent) panels: QueryList<PanelComponent>;
ngAfterContentInit() {
this.panels.forEach((panel) => {panel.active = false;});
}
}
PanelComponent如下:
export class PanelComponent {
@Input() active: boolean;
@Input() title: string;
toggle() {
this.active = !this.active;
}
}
手风琴正在工作,但是打开一个新面板时,我需要关闭所有面板。
我认为这可以通过两种方式完成:
在PanelComponent中,可以访问AccordionComponent上的方法。
这种方法会将一个面板设置为活动状态,而其余面板则为不活动状态。
我不知道如何从子组件(面板)访问父组件(手风琴)
使用包含面板的AccordionService:
panels: PanelComponent[] = [];
然后将该服务注入“手风琴和面板”中。
这似乎是逻辑,但随后我停止使用@ContentChildren(PanelComponent)。
从某种意义上讲,这破坏了手风琴与面板之间的关系。
我应该使用哪种解决方案?还是另一个?
我在2个解决方案中都缺少什么(我不知道如何实现解决方案1)。
答案 0 :(得分:1)
关于第1点,您可以注入父组件,如下所示:
constructor(
@Inject(forwardRef(() => AccordionComponent)) private accordion: AccordionComponent,
...)
使用服务也可以,但是在这种简单的情况下,恕我直言,似乎还有更多工作。
答案 1 :(得分:0)
您可以轻松地使用事件发射器来解决您的目的。
对您的代码所做的更改:
panel.component.ts
@Input() activate: string;
@Input() title: string;
@Output() closeOtherPanels: EventEmitter<string> = new EventEmitter();
active : boolean = false;
ngOnChanges(changes : SimpleChanges){
if(changes.activate){
this.active = this.activate == this.title;
}
}
toggle() {
this.active = !this.active;
if(this.active){
this.closeOtherPanels.emit(this.title);
}
}
app.component.ts
export class AppComponent {
activeTitle : string="";
name = 'Angular';
closeOtherPanels(value){
this.activeTitle=value;
}
}
app.component.html
<accordion>
<panel title="Panel 1 title" [activate]="activeTitle"
(closeOtherPanels)="closeOtherPanels($event)">Panel 1 content</panel>
<panel title="Panel 2 title" [activate]="activeTitle" (closeOtherPanels)="closeOtherPanels($event)">Panel 2 content</panel>
<panel title="Panel 3 title" [activate]="activeTitle" (closeOtherPanels)="closeOtherPanels($event)">Panel 3 content</panel>
<panel title="Panel 4 title" [activate]="activeTitle" (closeOtherPanels)="closeOtherPanels($event)">Panel 4 content</panel>
</accordion>