在我的自定义指令中,我根据数据源数组中的对象数量向DOM添加元素。我需要在每个对象中观察特定属性。当我将这些元素添加到DOM时,我想在checked
数组中的每个对象的toppings
属性上设置$ watch,但它不起作用,我不知道为什么。我在函数内部设置了一个断点,当属性从true变为false或false变为true时应调用该断点,但永远不会调用该函数。原因很明显吗?我只是在学习Angular,所以我很容易犯一个愚蠢的错误。
$scope.bits = 66; (i.e. onions and olives)
$scope.toppings = [
{ topping: 1, bits: 2, name: 'onions' },
{ topping: 2, bits: 4, name: 'mushrooms' },
{ topping: 3, bits: 8, name: 'peppers' },
{ topping: 4, bits: 16, name: 'anchovies' },
{ topping: 5, bits: 32, name: 'artichokes' },
{ topping: 6, bits: 64, name: 'olives' },
{ topping: 7, bits: 128, name: 'sausage' },
{ topping: 8, bits: 256, name: 'pepperoni' }
]
模型中的每个对象都会获得一个新的checked
属性,该属性将为true或false。
注意:对象数组最多包含十几个项目。表现不是问题。
link: function link(scope, iElement, iAttrs, controller, transcludeFn) {
<snip>
// At this point scope.model refers to $scope.toppings. Confirmed.
angular.forEach(scope.model, function (value, key) {
// bitwise: set checked to true|false based on scope.bits and topping.bits
scope.model[key].checked = ((value.bits & scope.bits) > 0);
scope.$watch(scope.model[key].checked, function () {
var totlBits = 0;
for (var i = 0; i < scope.model.length; i++) {
if (scope.model[i].checked) totlBits += scope.model[i].bits;
}
scope.bits = totlBits;
});
});
<snip>
答案 0 :(得分:2)
对象数组:
$scope.toppings = [
{ topping: 1, bits: 2, name: 'onions' },
{ topping: 2, bits: 4, name: 'mushrooms' },
{ topping: 3, bits: 8, name: 'peppers', checked:undefined /*may be*/ }
];
观看使用AngularJs $ WatchCollection:
我们将创建一个我们正在观察集合的元素属性数组(objects
),而不是监视上面的.checked
数组,这可以改变对象中的任何属性。 / p>
我们filter
数组的元素仅监视那些.checked
定义的元素和map
元素到角watchCollection
的数组。
当更改触发时,我将使用lodash difference方法比较旧的和新的(.checked
)数组,以获得确切的更改元素。
$scope.$watchCollection(
//Watch Function
()=>($scope.toppings.filter(tp=>tp.checked!=undefined).map(tp=>tp.checked)),
//Listner
(nv,ov)=>{
if(nv==ov||nv=="undefined")return;
//Use lodash library to get the changed obj
let changedTop= _.difference(nv,ov)[0];
//Here you go..
console.log("changed Topping",changedTop);
})
答案 1 :(得分:1)
$ scope。$ watch的watchExpression参数应该是字符串或函数。我没有对此进行过广泛的实验(尽可能避免使用明确的手表),但我认为当你观看简单的手表时它也会起作用。范围属性作为对象引用,但对于更复杂的引用则不太好。
我认为如果您将引用作为字符串提供,例如&#39;模型[&#39; +键+&#39;]。已选中&#39;那么你可能会取得一些成功(我只是这样说,因为我之前已经用$ watchCollection做了类似的事情。)
或者你应该能够提供一个功能,例如
$scope.$watch(function() { return scope.model[key].checked; }, function() { ... });
希望这有帮助!
答案 2 :(得分:1)
使用MAP收集所需的所有属性值+将它们转换为小字符串表示形式(在本例中为1和0),然后将它们连接成一个可以观察到的字符串。
打字稿示例:
$scope.$watch(
() => this.someArray.map(x => x.selected ? "1" : "0").join(""),
(newValue, oldValue, scope) => this.onSelectionChanged(this.getSelectedItems()));
答案 3 :(得分:0)
改为使用$watchCollection。
来自docs:
$ watchCollection(obj,listener); Shallow监视对象的属性,并在任何属性发生更改时触发(对于数组,这意味着要观察数组项;对于对象映射,这意味着要观察属性)。如果检测到更改,则会触发侦听器回调。
通过标准的$ watch操作观察obj集合,并在每次调用$ digest()时检查obj集合,以查看是否已添加,删除或移动任何项目。 只要obj中的任何内容发生变化,就会调用监听器。示例包括添加,删除和移动属于对象或数组的项目。