AngularJS: view a specific property in an array of objects to change the value of a property

In my custom directive, I add elements to the DOM based on the number of objects in my data array. I need to look at a specific property in each object. When I add these elements to the DOM, I want to set $ watch to the checked property of each object in the toppings array, but it does not work, and I donโ€™t know why. I set a breakpoint inside the function that should be called when the property changes from true to false or false to true, but this function is never called. Is the reason obvious? I am just learning Angular, so I can easily make a stupid mistake.

 $scope.bits = 66; (ie 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' } ] 

Each object in the model receives a new checked property, which will be true or false.

NOTE: an array of objects will contain no more than a dozen elements. Performance is not a concern.

 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> 
+5
source share
4 answers

The watchExpression parameter in $ scope. $ watch must be either a string or a function. I have not experimented much with this (I try to avoid explicit observations where possible), but I think this also works when you look at the โ€œsimpleโ€ properties of a region as object references, but not so well with more complex references.

I think if you specify the link as a string, for example. 'model [' + key + '] .checked', then you may have some success (I just say this because I used to do something similar with $ watchCollection).

Alternatively, you should be able to provide a function, e.g.

$scope.$watch(function() { return scope.model[key].checked; }, function() { ... });

Hope this helps!

+1
source

Array of objects:

 $scope.toppings = [ { topping: 1, bits: 2, name: 'onions' }, { topping: 2, bits: 4, name: 'mushrooms' }, { topping: 3, bits: 8, name: 'peppers', checked:undefined /*may be*/ } ]; 

Watch using AngularJs $ WatchCollection:

Instead of controlling the objects array, which can be changed for any property of the object, we will create an array of properties of the elements for which we observe a collection ( .checked ).

We filter elements of the array should control only those elements that have .checked and map , for the array for angular watchCollection .

When the change changes, I will compare the old and new arrays ( .checked ) to get the exact changed element using the lodash difference method.

  $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); }) 
+2
source

You use MAP to collect all the property values โ€‹โ€‹you need + convert them to a small string representation (in this case 1 and 0), and then combine them into a string that you can observe.

A typescript example:

  $scope.$watch( () => this.someArray.map(x => x.selected ? "1" : "0").join(""), (newValue, oldValue, scope) => this.onSelectionChanged(this.getSelectedItems())); 
+1
source

Use $ watchCollection instead.

From the docs:

$ watchCollection (obj, listenener); Shallow monitors the properties of the object and fires whenever a property changes (for arrays, this means viewing the elements of the array, and for maps of objects, viewing the properties). If a change is detected, the listener is called back.

The obj collection is observed through the standard $ watch operation and is checked every time $ digest () is called to see if any items have been added, removed or moved. The listener is called whenever something inside the object has been changed. Examples include adding, deleting, and moving elements that belong to an object or array.

0
source

Source: https://habr.com/ru/post/1205458/


All Articles