Angularjs: select update without updating ng model

I created the following example so that you can see exactly what is happening: http://jsfiddle.net/8t2Ln/101/

The same thing happens if I use ng-options. I have another reason for this, but to simplify the example, this part came out.

As you can see, by default it has two options. I am showing the selected ng model value next to select so you can see what it is. When you use the top to add a third option, it sets the value to the value of this new option, as evidenced by the displayed value of the ng model next to the selection, but the selection itself does not change to show the correct value is selected.

Below is an example of the code from the link:

var testApp = angular.module('testApp', ['ngRoute']); testApp.controller('Ctrl', function ($scope) { $scope.newInput = ''; $scope.inputDevice = [ { value: '1', label: 'input1' }, { value: '2', label: 'input2' } ]; $scope.selectedDevice = ''; $scope.addType = function () { var newElem = { label: $scope.newInput, value: '3' }; $scope.inputDevice.push(newElem); $scope.selectedDevice = newElem.value; }; }); 

And here is the html:

 <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 }}">{{ i.label }} - {{ i.value }}</option> </select> {{ selectedDevice }}</div> </div> 
+54
javascript angularjs angular-ngmodel
Oct 06 '14 at 7:25
source share
5 answers

That is why you should not use ngRepeat to select selection options. Instead, use ngOptions :

 <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 to select options. There are at least two good reasons. ngRepeat creates a separate child region for each iteration, which is not needed with the option tag. Another important caveat is that with ngRepeat you can only bind select to primitives such as strings, but you cannot write an object to ngModel with it.

Below is a demo.

 angular.module('demo', []).controller('DemoController', function($scope) { $scope.newInput = ''; $scope.inputDevice = [ {value: '1', label: 'input1'}, {value: '2', label: 'input2'} ]; $scope.selectedDevice = ''; $scope.addType = function() { var newElem = { label: $scope.newInput, value: Number($scope.inputDevice[$scope.inputDevice.length - 1].value) + 1 }; $scope.inputDevice.push(newElem); $scope.selectedDevice = newElem.value; $scope.newInput = ''; }; }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script> <div ng-app="demo" ng-controller="DemoController"> <form ng-submit="addType()"> <input type="text" ng-model="newInput" /> <button type="submit">Add Type</button> </form> <select ng-model="selectedDevice" ng-options="i.value as (i.label + ' - ' + i.value) for i in inputDevice"> <option>Select</option> </select> {{ selectedDevice }} </div> 
+80
Oct 06 '14 at 7:35
source share

The problem is that since you are not using ng-options , the browser did not finish rendering the moment you set the new selectedDevice . If you are using ng-options , you can use this workaround. Use $timeout to wrap your $scope.selectedDevice = newElem.value; to ensure that it starts after the browser completes the changes using ng-repeat .

I also added code to increase the next value for sequential additions, because hard coding it to "3" meant that the third parameter would be constantly selected, even when more was 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> 
+7
06 Oct '14 at 7:59
source share

I had a similar problem, and the reason is that my key was a number, but when I tried to set a different value, I sent a string. The workaround in this case is to force the model to be set 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; } 
+4
Mar 06 '15 at 9:42
source share

I had the same problem. For me, it decided to convert a number to a string. Example:

 $scope.selectedDevice = "" + newElem.value; 
+1
Nov 10 '16 at 18:01
source share

I had the same problem as select, not updating when updating the ng model. I extracted the value for the ng model from a function that extracted an object from an array based on a pair of keys, values.

At the same time, the returned object had the hashkey $$hashKey: "object:115" property

The problem arose when I created a copy of the object using angular.copy, which removed this hashkey property and therefore will not be selected.

After I reorganized the code to get the ng-model value after angular.copy, the problem was resolved.

 ConstructorReviewers: function (oItem) { this.PERSON_ID = oItem.PERSON_ID; this.CHAIR_PERSON = oItem.CHAIR_PERSON; /* // Commented this part and added it to EditItem function this.oDepartment = CommonFactory.FindItemInArray(vm.oCommittee.arrDepartments, 'NAME', this.DEPARTMENT, 'item'); */ this.EditItem = function () { vm.EditItemOriginal = this; angular.copy(this, vm.EditItem); // After this update the ng-model into vm.EditItem.oTitle object vm.EditItem.oTitle = CommonFactory.FindItemInArray(vm.oCommittee.arrTitles, 'TITLE', vm.EditItem.TITLE, 'item'); vm.Popup.ShowPopup(true, 'new_edit', Constants.Mentoring.Popup.Edit); } } 
0
Dec 10 '15 at 7:15
source share



All Articles