使用ngRepeat更改为父组件数组不会触发子$ onChanges

时间:2017-09-12 21:40:58

标签: angularjs angularjs-ng-repeat angularjs-components

我正在使用父组件和子组件。子组件是单向数据绑定('<')到通过父组件中的数组通过ng-repeat得到的值。

<li ng-repeat="item in $ctrl.items">
  <child-component item="item"></child-component>
</li>

组件:

var childComponent = {
  bindings: {
    item: '<'
  },
  controller: 'ChildComponentController',
  template: '<div>{{ $ctrl.item.name }}</div>'
}

也许我误解了$onChanges应该如何工作,但似乎更新父控制器中的项目数组应该调用孩子中的$onChanges()。它按预期更新视图。 $onChanges()会在初始页面加载时触发每个项目,但不会为更改而触发。

以下是我用来更新父数组的代码:

function change() {
  var item = angular.copy(this.items[1]);
  item.name = 'baz';
  angular.copy(item, this.items[1]);
}

Full Plunk:https://plnkr.co/edit/x7WA08

我最终要完成的是在子控制器上设置一个布尔this.updated,以在视图中显示更新的指示符。为简单起见,plunk只执行console.log()

我发现了大量的例子来传达从孩子到父母的变化(这看起来更复杂,因为它与单向绑定的方向相反),但没有更新孩子的父母有一个ng-repeat。这似乎应该有效。

我在这里缺少什么?

更新

我忘了提及,我正在使用组件和$onUpdate,因为我正试图转向面向组件的架构和Angular2兼容性。我希望找到一个符合这一目标的解决方案。

2 个答案:

答案 0 :(得分:1)

您是否尝试过使用 $ watch 角度服务?

尝试将 ChildComponentController 更改为:

org.apache.commons.lang3.ArrayUtils

答案 1 :(得分:0)

onChanges仅在对象引用更改时(或在值是原始类型的情况下更改)时触发。

由于您要复制回原始对象,所以原始对象引用不会更改。

要触发一项更改的onChanges,可以将更新后的新副本拼接到数组中的同一位置。

但是,这将作为ng-repeat的新对象出现,因此onFirstChange()将为true。 如果您希望将其标记为更新,那么我们需要复制ng-repeat用来跟踪集合中项目的任何内容。在这种情况下,由于未指定“ track by”,因此默认为$$ hashKey。

function change() {
    var item = angular.copy(this.items[1]);
    item.name = 'baz';

    // Retain the track by id. In this case $$hashKey
    // So that it gets flagged as an update instead of isFirstChange()
    item.$$hashKey = this.items[1].$$hashKey;

    // Trigger onChanges for the single updated item
    this.items.splice(1, 1, item);

    // OR trigger onChanges for all items
    // This will make isFirstChange() true for all items as they will
    // lose $$hashKey. If you have a 'track by' specified then isFirstChange()
    // will be false.
    //this.items = angular.copy(this.items);
}