Angularjs: select not updating when ng-model is updated
This is exactly why you should not use ngRepeat
to render select options. You should use ngOptions
instead:
<select ng-model="selectedDevice" ng-options="i.value as (i.label + '-' + i.value) for i in inputDevice"> <option></option></select>
In general, avoid using ngRepeat for rendering select options. There are at least two good reasons. ngRepeat
creates separate child scope per iteration, which is not needed in case of option tag. Another important caveat is that with ngRepeat
you can only bind select to primitives like strings, but you won't be able to write object to ngModel with it.
Here is a demo below.
The problem is that, since you're not using ng-options
the browser had not finished rendering at the point when you set the new selectedDevice
. If you're set on on using ng-options
you can use this workaround. Use $timeout
to wrap your $scope.selectedDevice = newElem.value;
to ensure it runs after the browser has finished rendering the changes with ng-repeat
.
I also added code to increment the next value on successive adds because hardcoding it to '3' meant that the third option would continually be selected even when more are added.
var testApp = angular.module('testApp', ['ngRoute']);testApp.controller('Ctrl', function($scope, $timeout) { $scope.newInput = ''; $scope.inputDevice = [{ value: '1', label: 'input1' }, { value: '2', label: 'input2' }]; $scope.selectedDevice = ''; $scope.addType = function() { var last = Number($scope.inputDevice[$scope.inputDevice.length - 1].value) + 1; var newElem = { label: $scope.newInput, value: last.toString() }; $scope.inputDevice.push(newElem); $timeout(function() { $scope.selectedDevice = newElem.value; }, 0); };});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular-route.js"></script><div ng-app="testApp"> <div ng-controller="Ctrl"> <p> <input type="text" ng-model="newInput" /> <br /> <button ng-click="addType()">Add Type</button> </p> <select ng-model="selectedDevice"> <option></option> <option ng-repeat="i in inputDevice" value="{{ i.value }}" ng-selelected="{{ selectedDevice == i.value }}">{{ i.label }} - {{ i.value }}</option> </select> {{ selectedDevice }} </div></div>
I had a similar problem and the reason was that my key was a number, but when trying to set another value I was sending a string. The workaround in this case is to force to set the model value to the same type as the key.
eg:
<select ng-model="model" ng-options="option.{{ key }} as option.{{ label }} for option in options"> <option value="">{{ emptyLabel }}</option></select>
if (scope.options.length > 0) { scope.keyType = typeof(scope.options[0][scope.key]);}
...
if (scope.keyType == 'number') { scope.model = parseInt(newVal, 10);} else { scope.model = newVal;}