我有一组卡片对象
...
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,但我不知道这是如何或如果这可以帮助我解决我的问题。
任何建议指出我正确的方向是值得赞赏的。
UPDATE
我在卡组件中的有效设置器是这样的
@Input()
set active(active: boolean) {
this._active = active;
}
我需要能够在任何时候更改所有卡片,换句话说,“选择/取消全选”选项。
解决了!
以suggestion from @Tim Klein为例,我订阅了QueryList的changes
,并且能够将我的组件放入一个数组中,当QueryList更改时我会更新它。现在我只是迭代组件数组并调用我的active
setter。
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
});
}
我认为您可能遇到的问题是,一旦调用了afterViewInit
生命周期事件,您的动态组件仍然没有加载。因此,如果您在cardList.toArray()
中调用afterViewInit
,它将返回一个空列表,因为您的组件尚未添加到父组件的视图中。
你应该尝试订阅changes
observable(比如this example),并在回调中调用你的逻辑来改变子组件的状态。
另一种选择是简单地为您的子组件提供另一个输入,该输入可以为其活动状态接受布尔值。
然后,当您设置Card
对象列表时,只需迭代并更改一些active
属性。只需在您父组件的模板中将该属性与name
一起设置即可。