Angular 4,5, как определить, будет ли изменено содержание ng в дочернем компоненте

У меня есть родительский компонент, как это. Поэтому количество пунктов в меню зависит от модели. И модель меняется.

<parent>
<menu>
  <item *ngIf="model.info">
   ... some data
  <item *ngIf="model.comments">
  .... some data 
  <item *ngIf="model.attachments">
   ... some data
  <item *ngIf="model.orders">
  .... some data
 </menu>
</parent>

Родительский компонент:

 export class Parent {
   @Input() public model: any;
 }   

Где menu - это сам компонент, использующий ng-контент, подобный этому, я создаю меню на основе количества menuItems.

selector: 'menu',
template: ` <ul class="nav"
    <li *ngFor="let item of items"  [class.active]="item.active"
    <a class="btn" (click)="menuItemClicked(item)"> </a>
    </li>
    </ul>

  <div class="content">
     <ng-content></ng-content>
  </div>

`
export class MenuComponent  {
  @ContentChildren(MenuItem) items;

  ngAfterContentInit() {
     this.setActiveMenuItem();
  }

  public menuItemClicked(item) {
    this.changeActiveItem(item)
  }


  private setActiveItem() {
      const items = this.items.toArray();
      const actives = this.items.filter(i => i.active);

      if (!actives.length && items.length) {
         items[0].active = true;
      }
  }

  private changeActiveItem(item) {
      const items = this.items.toArray();
      items.forEach(i => i.active = false);
      item.active = true;
  }

}

Если сам элемент menuItem является компонентом, который использует ng-content:

@Component({
selector: 'item',
template: `
   <ng-content *ngIf="active"></ng-content>
`
})
export class MenuItemComponent {
  @Input() active = false;

  public setActive() {
    this.active = true;
  }

  public setNotActive() {
    this.active = false;
  }

}

Родительский компонент используется так:

<app>
    <parent *ngIf="model.displayMenu" [model]="model"></parent>
</app>

Таким образом, он создается только один раз, а затем изменения модели на основе действий пользователя (клики и т. Д.)

Теперь в чем проблема? Проблема в том, что я создал родительский компонент. И в моем варианте использования модель меняется. Я точно знаю, когда меняется модель, но дело в том, что при этом изменении я всегда хочу, чтобы первый элемент меню был активным при этом изменении.

Моя проблема в том, что я не могу использовать хук ngAfterViewInit, потому что элементы еще не там. Детектированию угловых изменений требуется некоторое время, чтобы изменить это содержимое. Если я использовал ngAfterViewInit, пункты меню в этом хуке еще не обновляются. Я не хочу использовать ngAfterViewChecked, потому что он постоянно запускает обнаружение изменений и вызывает проблемы с производительностью (за этим постоянно меняется поток информации о модели).

Пример: у меня активен четвертый пункт меню и изменения модели. Следующая модель имеет только 2 пункта меню, и я хочу, чтобы пункт меню плавно переключался на 1-й пункт меню. Если я этого не сделаю, то получу пустой контент.

Как это можно решить?

1 ответ

Вы можете просто реализовать свой ContentChildren с помощью установщика:

items: QueryList<MenuItem>;

@ContentChildren(MenuItem) 
set menuItems(items) {
    this.items = items;
    this.setActiveMenuItem();
}

MenuItems-setter вызывается, когда изменяются участники.

Надеюсь, что это поможет, и я правильно понял вашу проблему.

Другие вопросы по тегам