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
对象永远不会更新。
我如何 $watch
在 ids[$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
}
在我的 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
对象永远不会更新。
我如何 $watch
在 ids[$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
}