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 вызывается, когда изменяются участники.
Надеюсь, что это поможет, и я правильно понял вашу проблему.