【问题标题】:Change to parent component array with ngRepeat doesn't trigger child $onChanges使用 ngRepeat 更改为父组件数组不会触发子 $onChanges
【发布时间】:2018-02-21 11:14:37
【问题描述】:

我正在使用父组件和子组件。子组件是单向数据绑定 ('<') 到一个通过 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 应该如何工作,但似乎更新父控制器的 items 数组中的项目应该在子控制器中调用 $onChanges()。它按预期更新视图。 $onChanges() 在初始页面加载时为每个项目触发,但不会为更改触发。

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

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

完整版:https://plnkr.co/edit/x7WA08

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

我找到了很多将更改从子级传递回父级的示例(这似乎更复杂,因为它与单向绑定的方向相反),但没有一个从父级更新子级带有 ng 重复。这似乎应该可以工作。

我在这里错过了什么?

更新

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

【问题讨论】:

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


    【解决方案1】:

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

    只需尝试将 ChildComponentController 更改为:

    function ChildComponentController($scope) {
      $scope.$watch('$ctrl.item.name', function() {
        alert($scope.$ctrl.item.name);
      });
    }
    

    【讨论】:

    • 感谢您的回复。这确实有效。我忘了在我的问题中提到我使用组件和$onChanges 的原因是我正在尝试向 Angular2 兼容性迈进。据我了解,$scope$watch 已不再可用。
    【解决方案2】:

    onChanges 只会在对象引用发生变化时触发(或者如果它是原始类型,则在值发生变化时)。

    由于您正在复制回原始对象,因此原始对象引用不会更改。

    要为已更改的一项触发 onChanges,您可以将更新的新副本拼接回数组中的相同位置。

    但是,这将作为 ng-repeat 的新对象出现,因此 onFirstChange() 将为真。 如果您希望将其标记为更新,那么我们需要复制 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-06-15
      • 2021-02-15
      • 2018-10-30
      • 2018-04-30
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 2020-09-02
      • 2017-03-03
      相关资源
      最近更新 更多