使用NgFor创建子组件,然后调用发出事件的方法

时间:2016-12-03 16:48:17

标签: angular ngfor

我可以想到一些方法可以解决这个问题,但我想对大多数' Angular' 的做法提出一些建议。

我把an example of what I'm doing放在一起。

主要组件使用NgFor迭代列表并创建一堆子组件。
每个子组件在单击时发出一个由父组件拾取的事件。每个孩子也有一个方法update()

我想要的是我的主要组件获取对任何一个孩子发出事件并引用其update()方法的引用的正确方法。

看起来非常简单(可能非常简单),但它是我构建的应用程序的一个核心功能,所以我希望尽可能干净整洁。

为你提供帮助

2 个答案:

答案 0 :(得分:4)

最简单的方法是使用模板变量来引用子组件:

<my-child #child *ngFor="let row of rowList;" [id]="row.name"
          (onMD)="processClick($event); child.update()"></my-child>

更新了演示:http://plnkr.co/edit/zA80iNsLHHULGx9Rbffw?p=preview

答案 1 :(得分:3)

由于Angular 2采用了单向数据流范例,我认为解决这个问题的“最”Angular'方式是调用update()方法所有。子组件的状态应由父组件提供。

每当点击发生时,应在App(父)组件中计算新状态,并将其传递给ChildComponent

这样,您需要通过附加属性(例如clicked)扩展父级中保存的状态:

rowList = [{name: "Alice", clicked: false}, ...];

(当然,由于undefinedfalse具有相同的逻辑值,因此不需要显式声明。)

单击,在处理程序方法中,计算新状态。在这种情况下,它只是一个简单的布尔值更改:

processClick(id){
  this.recentClick = id;
  // Create the new array for immutability benefits.
  this.rowList = this.rowList.map(person => {
    if (person.name === id) {
      return {name: person.name, clicked: true};
    } else {
      return person;
    }
  })
}

与任何其他@Input一样,该值会传递给孩子。

<my-child *ngFor="let row of rowList;" [id]=row.name [clicked]=row.clicked (onMD)="processClick($event)"></my-child>

现在,子组件可以根据clicked属性的值更改其行为。作为奖励,当使用不可变数据时,您可以将更改检测策略更改为some performance benefitsonPush

@Component({
    // ...
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent {
  @Input() clicked: boolean;

  get prefix() {
    return this.clicked ? "Bye!" : "Hi";
  }
  // ...
}

这种方法有很多好处。

  • 您没有隐藏在子组件中的隐藏状态。父母的“词”是绝对的(所谓的“单一真理来源”)。
  • 父母并不真正需要了解或关心孩子对数据做什么或何时需要更新。
  • 您可以轻松地将数据提取到其他位置,并且您无需编写任何使update()行为有效的代码。

完整实施如下所示:http://plnkr.co/edit/IP8iLKxKGCjHOdgPHJ0h?p=preview