从子组件访问父组件。使用服务? @ContentChildren呢?

时间:2019-01-28 18:07:50

标签: angular angular6 angular7 angular-components

我创建了一个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;
  }

}

手风琴正在工作,但是打开一个新面板时,我需要关闭所有面板。

我认为这可以通过两种方式完成:

  1. 在PanelComponent中,可以访问AccordionComponent上的方法。
    这种方法会将一个面板设置为活动状态,而其余面板则为不活动状态。

    我不知道如何从子组件(面板)访问父组件(手风琴)

  2. 使用包含面板的AccordionService:

    panels: PanelComponent[] = [];   
    

    然后将该服务注入“手风琴和面板”中。

    这似乎是逻辑,但随后我停止使用@ContentChildren(PanelComponent)。

    从某种意义上讲,这破坏了手风琴与面板之间的关系。

我应该使用哪种解决方案?还是另一个?

我在2个解决方案中都缺少什么(我不知道如何实现解决方案1)。

2 个答案:

答案 0 :(得分:1)

关于第1点,您可以注入父组件,如下所示:

constructor(
  @Inject(forwardRef(() => AccordionComponent)) private accordion: AccordionComponent, 
  ...)

使用服务也可以,但是在这种简单的情况下,恕我直言,似乎还有更多工作。

答案 1 :(得分:0)

您可以轻松地使用事件发射器来解决您的目的。

See this stackblitz

对您的代码所做的更改:

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>

相关问题