user3556789 user3556789 - 4 months ago 17
AngularJS Question

AngularJS: refresh ng-options when property source object changes

Full description:
I have list of options with multiple properties (not just key-value pair):

[
{
id: 1,
name: "111",
some: "qqq"
},
{
id: 2,
name: "222",
some: "www"
}
];


And select defined as:

<select name="mySelect" id="mySelect"
ng-options="option.name for option in opts track by option.id"
ng-model="mod1"></select>


Depending on app logic, extra property may change:

{
id: 2,
name: "222",
some: "www1"
}


But actual list in Select doesn't change!
However, if name changes, then entire optionList will be refreshed.

In short you can see demo on JSFiddle OR JSFiddle. I prepared 2 very similar examples:


  1. When button is clicked only extra property updates

  2. When button is clicked - both extra property and key receive new value



Does anybody know solution?

UPDATE



For now I'm solving that issue with
update + delay + update
solution:

this.click = function(){
$scope.opts = {};
$timeout(function() {
$scope.opts = { /* NEW OBJECT */};
}, 0);
}

Answer Source

OK, so I think I understand what you want, which is to be able to select an option whose nested values may have changed since the list was rendered in the DOM.

Based on that understanding, I believe that the plunker I have created illustrates a solution for you. If you select one of the options, and change the child value in the input field, two-way binding will update the model.

Basically, it is taking the users selection, and on select change, re-assigning the selected object to reference the original option in the options array. This will allow two-way binding to occur. If you view the code, you will see that the input fields are updating the option list itself ($scope.options), where-as the model that is being displayed is $scope.formData.model.

https://plnkr.co/edit/DLhI7t7XBw9EbIezBCjI?p=preview

HTML

<select 
  name="mySelect"
  id="mySelect"
  ng-model="formData.model"
  ng-change="onChange(formData.model)"
  ng-options="option.name for option in options track by option.id"></select>

  SELECTED CHILD: {{formData.model.child.name}}

<hr>

<div ng-repeat="option in options">
  Child Name for {{ option.name }}: <input ng-model="option.child.name">
</div>

JS

  $scope.onChange = function(option) {

    angular.forEach($scope.options,function(optionItem){
      if (optionItem.id == option.id){
         $scope.formData.model = optionItem;
      }
    })


  }

  $scope.options = [
    {
      id: 1,
      name: "111",
      child: {
        id: 11,
        name: "111-1"
      }
    },
    {
      id: 2,
      name: "222",
      child: {
        id: 22,
        name: "222-1"
      }
    }
  ];

  $scope.formData = {
    model: $scope.options[0]
  };