Angular: $scope.$watch 嵌套集合

Angular: $scope.$watch a nested collection

在我的 Angular 应用程序中,我有一个复选框列表,它是通过嵌套的 ng-repeat 生成的,如下所示:

<div ng-repeat="type in boundaryPartners">
    <div class="row">
        <div class="col-xs-12 highlight top-pad">
            <div ng-repeat="partner in type.partners" class="highlight">
                <label class="checkbox-inline">
                    <input type="checkbox" value="partner"
                    ng-model="ids[$parent.$index][$index]"
                    ng-true-value="{{partner}}"
                    ng-false-value="{{undefined}}">
                    <p><span ></span>{{partner.name}}<p>
                </label>
            </div>
        </div>
    </div>
</div>

在我的控制器中:

$scope.ids = [];

$scope.$watchCollection('ids', function(newVal) {
    for (var i = 0, j = newVal.length; i < j; i++) {

        // Create new participatingPatners tier if it doesn't exist
        if(!$scope.report.participatingPartners[i]) $scope.report.participatingPartners[i] = {};

        // Give it an id
        $scope.report.participatingPartners[i].id = i + 1;

        // Map our values to it
        $scope.report.participatingPartners[i].entities = $.map(newVal[i], function(value, index) {
            return [value];
        });
    }

});

问题是,一旦我添加了每个顶级 ids 中的一个,这个 $scope.$watchCollection 就会停止观看,所以如果我从第一个嵌套列表中添加给定数量的输入,那么第二个列表中的另一个,我的 $scope.report.participatingPartners 对象永远不会更新。

我如何 $watchids[$parent.$index][$index] 内进行更改,确保在复选框被选中或未选中时更新我的​​对象?

你能试着观察对象是否相等吗:

$scope.$watchCollection('ids', function(newVal) {

}, true);

$watchCollection$watch 类似,它检查物理对象引用,但更进一步;它还深入一层并对这些属性进行参考检查。

您需要使用 $watch,但将 objectEquality 标志设置为 true。这将告诉 $watch 执行深度引用检查。根据正在观看的项目的深度,这可能会严重影响性能。

$watch(watchExpression, listener, [objectEquality]);

您正在创建一个数组数组:

$scope.ids = [
  [],
  [],
  //...
]

但使用 $watchCollection 来观察外部数组的变化,即 $scope.ids 的变化。这只会在嵌套数组变成不同的对象(或第一次创建)时识别变化。

可以 使用 $scope.$watch("ids", function(){}, true) - true 代表 "deep-watch",但那会非常浪费,因为这是一张昂贵的支票这将在每个摘要周期执行,无论是否单击复选框。

相反,使用 ng-change 触发处理程序:

<input type="checkbox" value="partner"
       ng-model="ids[$parent.$index][$index]"
       ng-change="handleCheckboxChanged()">
$scope.handleCheckboxChanged = function(){

  // whatever you wanted to do before in the handler of $watchCollection
}