Доступ к родительскому компоненту из дочернего компонента.Использовать сервис?Как насчет @ContentChildren? - PullRequest
0 голосов
/ 28 января 2019

Я создал аккордеонный компонент Angular 7 Пример SlackBlitz :

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[] = [];   
    

    Затем добавьте этот сервис в Accordion and Panel.

    Это выглядит логично, но затем я перестал использовать @ContentChildren (PanelComponent).

    В некотором смысле это нарушает связь между Аккордеоном и Панелью.

Какое решение мне следует использовать?Или другое?

Я что-то упустил в своих 2 решениях (я не знаю, как реализовать решение 1).

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Вы можете легко использовать генераторы событий для решения своей задачи.

См. Этот стек

Изменения, внесенные в ваш код:

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>

0 голосов
/ 28 января 2019

Что касается пункта 1, вы можете добавить родительский компонент, как показано ниже:

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

Использование службы также работает, но, кажется, немного больше работы для этого простого случая, ИМХО.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...