Search code examples
javascriptangularjsangularjs-scopelodashangularjs-ng-options

how can i update an item in a collection, without breaking angular databinding?


I have a collection of objects, I think this is called an associative array. Regardless, I would like to locate an item in that list and update it. As a side note this collection is the ng-model for a select. I know lodash has some of this type of functionality. I can find the item but I am not sure what is the best way to update the item so the data binding still works on my select.

Here is an example that doesn't work:

for (x = 0; x < $scope.RulesTemplates.length; x++)
 {
   if($scope.RulesTemplates[x].Name == $scope.TempRules.Name)
   {
     $scope.RulesTemplates[x] = $scope.TempRules;
   }
 }

Solution

  • Assuming a sample dataset, if you want to extend an existing object in an array that is bound to ng-options, you first need to make sure the angular has the array item being tracked by a specific unique property. Then you could just update the new item in the array at the respective place, angular will automatically perform the update in the bound select options (without re-rendering other option values). But that approach might not refresh already bound ng-model.

    Another simple approach using traditional loop:-

    <select ng-options="item.display for item in items" ng-model="selected"></select>
    

    and your update logic can just be:-

    for (x = 0, l = $scope.items.length; x < l; x++){
      var item = $scope.items[x];
      if(item.name == itemsUpdate.name) {
          angular.extend(item,itemsUpdate); //Extend it
          break;
      }
    }
    

    Demo1

    or since you are using lodash, probably less lines of code:-

    var item = _.first($scope.items, {name:itemsUpdate.name}).pop(); //Get the item add necessary null checks
    angular.extend(item, itemsUpdate);
    

    Demo2

    angular.extend will make sure underlying source object reference remains the same with updating the properties, you could also use lodash merge.