以编程方式设置动态添加的子组件的属性

时间:2019-04-15 18:47:48

标签: angular dynamically-generated

我有一组卡片对象

...
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(),但是QueryListtoArray()方法总是给我一个空数组。从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
  });
}

1 个答案:

答案 0 :(得分:1)

我认为您可能面临的问题是,一旦调用afterViewInit生命周期事件,您的动态组件仍然没有加载。因此,如果您要在cardList.toArray()内调用afterViewInit,它将返回一个空列表,因为您的组件尚未添加到父组件的视图中。

您应该尝试订阅changes可观察的对象(例如this example),并在回调中调用您的逻辑以更改子组件的状态。

更新

另一种选择是为子组件简单地提供另一个输入,该输入可以接受处于活动状态的布尔值。

然后,当您设置Card对象的列表时,只需遍历并更改某些active属性。只需在模板中为您的父组件设置该属性以及name