Toggle Sibling Component в угловой 5 - PullRequest
0 голосов
/ 22 мая 2018

Я пытаюсь получить событие щелчка по одному братскому компоненту, чтобы «услышать» его по другому.

Должен ли я передать событие вверх по цепочке к родителю, обнаружить изменение и затем каким-то образом передать его родному брату (другому дочернему элементу по отношению к родителю)?

Компоненты в шаблоне страницы:

<wrap>
  <toggler>Toggle the Box</toggler>
  <box>Box Content ...</box>
</wrap>

Компонент Toggler:

@Component({
  selector: 'toggler',
  template: `<div (click)="toggleBox()"><ng-content></ng-content></div>`,
})
export class TogglerComponent {
  @Output() toggle = new EventEmitter<boolean>();
  visible: boolean = false;
  toggleBox(): void {
    this.visible = !this.visible;
    this.toggle.emit(this.visible);
  }
}

Компонент Box: Как можно подобрать компонент блокасобытие переключения?

Базовый компонент:

@Component({
  selector: 'box',
  template: `<ng-content *ngIf="toggle"></ng-content>`,
})
export class BoxComponent {
  @Input() toggle: boolean;
}

1 Ответ

0 голосов
/ 22 мая 2018

Существует несколько способов установить связь между родственными компонентами:

1.Сервис

Первый вариант - иметь сервис с общедоступным наблюдаемым свойством и внедрить его в компоненты.

@Injectable()
export class ToggleService {

  private toggle = new Subject<boolean>();

  public $toggle = this.toggle.asObservable();

  constructor() { }

  setToggle(val: boolean){
    this.toggle.next(val);
  }

}

Оттуда ваши компоненты будут

TogglerComponent
export class TogglerComponent {


  constructor(toggleService: ToggleService){}

  visible: boolean = false;
  toggleBox(): void {
    this.visible = !this.visible;
    this.toggleService.setToggle(this.visible);
  }
}
BoxComponent
export class BoxComponent implements OnInit {

   constructor(toggleService: TogglerService){

   }

   ngOnInit(){
     this.toggleService.$toggle.subscribe(val => {
       // Do Something
     });
   }
}

Примечание. При таком подходе необходимо соблюдать осторожность с областью действия DI, поскольку необходимо, чтобы оба компонента совместно использовали один и тот же экземпляр службы.Поэтому ваш провайдер должен быть либо в родительском компоненте, либо в общем или родительском модуле.

2.Родительское свойство

Второй вариант - иметь свойство в родительском объекте и связать его с обоими компонентами.

Ваш ParentComponent будет чем-то похожим

export class ParentComponent implements OnInit {

  public toggle: boolean;

  constructor() { }

  ngOnInit() {
  }

  changeToggle(val){
    this.toggle = val;
  }

}

ИВаш шаблон просто связал бы эту функцию и свойство

<toggler (toggle)="changeToggle(toggle)"/>
<box [toggle]="toggle"/>

3.Решение BindingLess (не рекомендуется)

На основании вашего комментария существует другая альтернатива, использующая ViewChild, которая будет выглядеть примерно так:

export class ParentComponent implements AfterViewInit {

  @ViewChild(TogglerComponent)
  togglerComponent: TogglerComponent;

  @ViewChild(BoxComponent)
  boxComponent: BoxComponent

  constructor() { }

  ngAfterViewInit() {

    this.togglerComponent.toggle
      .subscribe(val => this.boxComponent.toggle = val)

  }

}

Для получения дополнительной информации вы можете проверить: https://angular.io/guide/component-interaction

...