我有一组卡片对象
...
cards: Card[];
...
ngOnInit() {
this.cardService.getCards.subscribe(r => { this.cards = r; });
}
我像这样在模板中添加子卡组件
<div id="cards-container">
<app-card *ngFor="let card of cards" [name]="card.name"></app-card>
</div>
Card组件的名称和某些样式取决于通过单击该组件切换的活动属性。
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
'styleUrls: ['./card.component.scss']
})
export class CardComponent {
private _name = '';
private _active = false;
// getters/setters
...
onClick(e) {
this.active = !this.active;
}
}
card.component.html
<div [ngClass]="{'card': true, 'active': _active}"
(click)="onClick($event)">
{{name}}
</div>
所有这些都很好。
问题:
在父组件中,我需要遍历*ngFor="let card of cards"
添加的所有卡组件,并将它们设置为活动或不活动,但是我不知道该怎么做。
我尝试过的事情:
我尝试使用@ViewChildren()
,但是QueryList的toArray()
方法总是给我一个空数组。从ViewChildren documentation中的有限示例中,我并不确定100%是否需要在父组件中添加其他指令,或者示例中的指令仅用于演示。所以我尝试的是
@ViewChildren(CardComponent) cardList: QueryList<CardComponent>;
我也尝试使用ViewContainerRef来使用类似于this answer的工具,但是我无法使其正常工作,这似乎并没有使我朝着正确的方向前进。我也查看了the documentation for ComponentRef,但看不到如何或是否可以帮助我解决问题。
感谢任何向我指出正确方向的建议。
更新
我在卡片组件中的活动二传手是这样的
@Input()
set active(active: boolean) {
this._active = active;
}
我需要能够在任何时候为所有卡更改此设置,换句话说,就是“全选/取消全选”选项。
已解决!
使用suggestion from @Tim Klein,我订阅了QueryList的changes
,并能够将我的组件放入一个数组中,当QueryList更改时,我将对其进行更新。现在,我仅迭代组件数组并调用我的active
设置器。
cards: CardComponent[];
@ViewChildren(CardComponent) cardList: QueryList<CardComponent>;
...
ngAfterViewInit(): void {
this.cards = this.cardList.toArray(); // empty array but that's okay
this.cardList.changes.subscribe((r) => {
this.cards = this.cardList.toArray(); // we get all the cards as soon as they're available
});
}
答案 0 :(得分:1)
我认为您可能面临的问题是,一旦调用afterViewInit
生命周期事件,您的动态组件仍然没有加载。因此,如果您要在cardList.toArray()
内调用afterViewInit
,它将返回一个空列表,因为您的组件尚未添加到父组件的视图中。
您应该尝试订阅changes
可观察的对象(例如this example),并在回调中调用您的逻辑以更改子组件的状态。
另一种选择是为子组件简单地提供另一个输入,该输入可以接受处于活动状态的布尔值。
然后,当您设置Card
对象的列表时,只需遍历并更改某些active
属性。只需在模板中为您的父组件设置该属性以及name
。