【问题标题】:Programmatically set attribute of dynamically added child component以编程方式设置动态添加的子组件的属性
【发布时间】:2019-04-16 03:55:53
【问题描述】:

我有一组卡片对象

...
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>

卡片组件有一个名字和一些样式,依赖于一个通过点击组件来切换的活动属性

@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,但我不知道这如何或是否可以帮助我解决我的问题。

感谢任何可以为我指明正确方向的建议。

更新

我在卡片组件中的active setter是这样的

@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
  });
}

【问题讨论】:

  • 哈哈我喜欢你的用户名

标签: angular dynamically-generated


【解决方案1】:

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

您应该尝试订阅 changes observable(如在 this example 中)并在回调中调用您的逻辑来更改子组件的状态。

更新

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

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

【讨论】:

  • 感谢您的建议。我在卡片组件的active 设置器上确实有一个@Input() 装饰器,但我需要能够在运行时的任何时间点“选择”/“取消选择”,而不仅仅是在第一次添加它们时。我会用更多信息更新我的问题。
猜你喜欢
  • 2012-08-20
  • 1970-01-01
  • 2014-06-11
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
相关资源
最近更新 更多