rodney757
rodney757

Reputation: 583

ngModel not updated when ngOptions change

How can I prevent angular from updating the ngModel when the ngOptions array changes? Angular seems to set ngModel to null when the ngOptions array changed.

.controller('myController', function($scope) {
    var vm = this;
    vm.options = [];
    vm.selected = null;
    vm.getOptions = function(id) {
        $http.get().done(function(response) {
            vm.options = response.data;
        });
    };
}

say vm.selected = "1";

when vm.getOptions is called, the select options are being repopulated as expected, but angular seems to set vm.selected to null

How can I keep vm.selected = "1" after vm.options changes?

EDIT:

so I tried to set vm.selected after vm.options was set, however angular set vm.selected to null after my controller code runs.

so I tried to do:

$timeout(function(selected) {
   vm.selected = selected;
}, 0, true, vm.selected);

this successfully sets vm.selected to the previous value, however the view isn't updated.

EDIT:

the html is:

<select name="myOption" ng-model="vm.selected"
    ng-options="option.id as option.name for option in vm.options track by option.id">
<option value="">Select an option</option>

here is a plunkr to demonstrate. 1st, select an option, the click the update option button.

Upvotes: 4

Views: 2198

Answers (3)

bhantol
bhantol

Reputation: 9616

This is one of such situation I got burnt myself due to not treating the model as object of the option and resorting to property of the selected option

How can I keep vm.selected = "1" after vm.options changes?

The vm.selected is a number not an object. It needs to be an object and must be the reference in the options

I made very small change to illustrate and get it to work.

First vm.selected treat it as object by following changes. Notice model is no longer optionId.

ng-options="option as option.optionTitle for option in vm.options track by option.optionId"

Second in the controller we are initializing the model as an object and a reference to the options.

vm.options = [{optionId: 1, optionTitle: "one"}, {optionId: 2, optionTitle: "two"}];
vm.selected = vm.options[1];

Also modified the plunkr for other changes related to optionId keeping unique. However those changes don't contribute to the point in question.

Upvotes: 0

hansmaad
hansmaad

Reputation: 18905

Be careful when using select as and track by in the same expression. ngOptions

You're using the id as value for ngModel. you cannot track option.optionId on this. You should use the option instance instead:

<select ng-model="vm.selected" 
        ng-options="option as option.optionTitle for option in vm.options track by option.optionId">
  <option value="">Select an option</option>
</select>

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope, $http) {
  var vm = this;
  vm.selected = null;
  vm.options = [{optionId: 1, optionTitle: "one"}, {optionId: 2, optionTitle: "two"}];
  vm.updateOptions = function() {
    vm.options.push({optionId: 3, optionTitle: "three"});
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  
<body ng-app="app" ng-controller="MainCtrl as vm">
    <select ng-model="vm.selected" ng-options="option as option.optionTitle for option in vm.options track by option.optionId">
      <option value="">Select an option</option>
    </select>
    <hr/>
    vm.selected = {{ vm.selected }}
    <br>
    <button ng-click="vm.updateOptions()">Update Options</button>
    <br>
</body>

Upvotes: 3

Nikhilesh Shivarathri
Nikhilesh Shivarathri

Reputation: 1670

Due to the numerous request for resetting the model on options change, Angular has made sure that the model value resets after the ng-options change for the versions > 1.4. However this will continue to work the same in the older versions of Angular.

Click here for the reference

In order to achieve the desired functionality, i would recommend you to use ng-repeat on options rather than ng-options on select.

<select ng-model="vm.selected">
  <option value="">Select an option</option>
  <option ng-repeat="option in vm.options track by option.optionId" value="{{option.optionId}}">{{option.optionTitle}}</option>
</select>

look at this plnkr example

hope this helps you!

Upvotes: 0

Related Questions