angularjsng-optionsangularjs-ng-options

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);
}

Solution

  • 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]
      };