Here is what seems to be bothering a lot of people (including me).
When using the ng-options
directive in AngularJS to fill in the options for a &
You can do this:
<select ng-model="model">
<option value="">Select</option>
<option ng-repeat="obj in array" value="{{obj.id}}">{{obj.name}}</option>
</select>
-- UPDATE
After some updates, user frm.adiputra's solution is much better. Code:
obj = { '1': '1st', '2': '2nd' };
<select ng-options="k as v for (k,v) in obj"></select>
This is how I resolved this. I tracked the select by value and set the selected item property to the model in my JavaScript code.
Countries =
[
{
CountryId = 1, Code = 'USA', CountryName = 'United States of America'
},
{
CountryId = 2, Code = 'CAN', CountryName = 'Canada'
}
]
<select ng-model="vm.Enterprise.AdminCountry" ng-options="country.CountryName for country in vm.Countries track by country.CountryId">
vm
is my controller and the Country in the controller retrieved from the service is {CountryId =1, Code = 'USA', CountryName='United States of America'}
.
When I selected another country from the select dropdown and posted my page with "Save", I got the correct country bound.
Instead of using the new 'track by' feature you can simply do this with an array if you want the values to be the same as the text:
<select ng-options="v as v for (k,v) in Array/Obj"></select>
Note the difference between the standard syntax, which will make the values the keys of the Object/Array, and therefore 0,1,2 etc. for an array:
<select ng-options"k as v for (k,v) in Array/Obj"></select>
k as v becomes v as v.
I discovered this just based on common sense looking at the syntax. (k,v) is the actual statement that splits the array/object into key value pairs.
In the 'k as v' statement, k will be the value, and v will be the text option displayed to the user. I think 'track by' is messy and overkill.
Run the code snippet and see the variations. Here is note for quick understanding
Example 1(Object selection):- ng-option="os.name for os in osList track by os.id"
. Here track by os.id
is important & should be there and os.id as
should NOT have before os.name
.
ng-model="my_os"
should set to an object with key as id like my_os={id: 2}
.Example 2(Value selection) :- ng-option="os.id as os.name for os in osList"
. Here track by os.id
should NOT be there and os.id as
should be there before os.name
.
ng-model="my_os"
should set to a value like my_os= 2
Rest code snippet will explain.
angular.module('app', []).controller('ctrl', function($scope, $timeout){
//************ EXAMPLE 1 *******************
$scope.osList =[
{ id: 1, name :'iOS'},
{ id: 2, name :'Android'},
{ id: 3, name :'Windows'}
]
$scope.my_os = {id: 2};
//************ EXAMPLE 2 *******************
$timeout(function(){
$scope.siteList = [
{ id: 1, name: 'Google'},
{ id: 2, name: 'Yahoo'},
{ id: 3, name: 'Bing'}
];
}, 1000);
$scope.my_site = 2;
$timeout(function(){
$scope.my_site = 3;
}, 2000);
})
fieldset{
margin-bottom: 40px;
}
strong{
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.10/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<!--//************ EXAMPLE 1 *******************-->
<fieldset>
<legend>Example 1 (Set selection as <strong>object</strong>)</legend>
<select ng-model="my_os" ng-options="os.name for os in osList track by os.id">
<option value="">--Select--</option>
</select>
{{my_os}}
</fieldset>
<!--//************ EXAMPLE 2 *******************-->
<fieldset>
<legend>Example 2 (Set selection as <strong>value</strong>. Simulate ajax)</legend>
<select ng-model="my_site" ng-options="site.id as site.name for site in siteList">
<option value="">--Select--</option>
</select>
{{my_site}}
</fieldset>
</div>
If you want to change the value of your option
elements because the form will eventually be submitted to the server, instead of doing this,
<select name="text" ng-model="text" ng-options="select p.text for p in resultOptions"></select>
You can do this:
<select ng-model="text" ng-options="select p.text for p in resultOptions"></select>
<input type="hidden" name="text" value="{{ text }}" />
The expected value will then be sent through the form under the correct name.
Here is how I solve this problem in a legacy application:
ng-options="kitType.name for kitType in vm.kitTypes track by kitType.id" ng-model="vm.itemTypeId"
vm.kitTypes = [
{"id": "1", "name": "Virtual"},
{"id": "2", "name": "Physical"},
{"id": "3", "name": "Hybrid"}
];
...
vm.itemTypeId = vm.kitTypes.filter(function(value, index, array){
return value.id === (vm.itemTypeId || 1);
})[0];
My HTML displays the option value properly.