Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I have read about it in other posts but couldn't figure out. I have array:

$scope.items = [
   {ID: '000001', Title: 'Chicago'},
   {ID: '000002', Title: 'New York'},
   {ID: '000003', Title: 'Washington'},
];

I want to render this

<select>
  <option value="000001">Chicago</option>
  <option value="000002">New York</option>
  <option value="000003">Washington</option>
</select>

And also I want to select option with ID=000002.

I have read this http://docs.angularjs.org/api/ng.directive:select and tried but can't figure out.

share|improve this question
up vote 708 down vote accepted

One thing to note is that ngModel is required for ngOptions to work... note the ng-model="blah" which is saying "set $scope.blah to the selected value".

Try this:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

Here's more from Angular's documentation (if you haven't seen it):

for array data sources:

  • label for value in array
  • select as label for value in array
  • label group by group for value in array = select as label group by group for value in array

for object data sources:

  • label for (key , value) in object
  • select as label for (key , value) in object
  • label group by group for (key, value) in object
  • select as label group by group for (key, value) in object

EDIT: For some clarification on option tag values in Angular

When you use ng-options, the values of option tags written out by ng-options will always be the index of the array item the option tag relates to. This is because Angular actually allows you to select entire objects with select controls, and not just primitive types. For example:

app.controller('MainCtrl', function($scope) {
   $scope.items = [
     { id: 1, name: 'foo' },
     { id: 2, name: 'bar' },
     { id: 3, name: 'blah' }
   ];
});
<div ng-controller="MainCtrl">
   <select ng-model="selectedItem" ng-options="item as item.name for item in items"></select>
   <pre>{{selectedItem | json}}</pre>
</div>

The above will allow you to select an entire object into $scope.selectedItem directly. The point is, with Angular, you don't need to worry about what's in your option tag. Let Angular handle that, you should only care about what's in your model in your scope.

Here is a plunker demonstrating the behavior above, and showing the html written out


EDIT 2: Dealing with the default option:

There are a few things I've failed to mention above relating to the default option.

Selecting first option and removing the empty option:

You can do this by adding a simple ng-init that sets the model (from ng-model) to the first element in the items your repeating in ng-options:

<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.name for item in items"></select>

Note: this could get a little crazy if foo happens to be initialized properly to something "falsy". In that case, you'll want to handle the initialization of foo in your controller, most likely.

Customizing the default option:

This is a little different, here all you need to do is add an option tag as a child of your select, with an empty value attribute, then customize it's inner text:

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="">Nothing selected</option>
</select>

Note: that in this case the "empty" option will stay there even after you select a different option. This isn't the case for the default behavior of selects under Angular.

A customized default option that hides after a selection is made:

If you wanted your customized default option to go away after you select a value, you can add an ng-hide attribute to your default option:

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="" ng-if="foo">Select something to remove me.</option>
</select>
share|improve this answer
7  
This generates the following <select class="ng-pristine ng-valid" ng:options="item.Title as item.ID for item in items" ng:model="blah"> <option value="0" selected="selected">4a611be3-e83e-4d00-b7a0-a0f400196643</op‌​tion> </select>. I need value to be Guid and Title to be option text. – Andrej Kaurin Oct 24 '12 at 14:11
3  
Turns out that those are the indices of the values, this is how angular can allow you to use objects as the value of your select box. Angular is doing a lot of stuff for you behind the scenes with select boxes, and you're not supposed to be worrying about the value attribute on your options. – Ben Lesh Dec 18 '12 at 15:30
22  
"...ngModel is required for ngOptions to work..." was the crux of the problem for me. Good answer. – tristanm May 23 '13 at 2:53
7  
I want to make love to this answer – Kamal Reddy Sep 19 '14 at 18:52
4  
I'm trying to use the last case (A customized default option that hides after a selection is made) but I found some problems. Instead of ng-if="foo" I've had to use ng-if=!foo to hide the default empty option when other option is selected. Also, the default empty option appear always at bottom of combo list. How I can put it at the beginning of the combo list? – Fran Herrero Apr 20 '15 at 13:14

I'm learning angularjs and was struggling with selection as well. I know this question is already answered but wanted to share some more code nevertheless.

In my test I have two listboxes: car makes and car models. Models list is disabled until some make is selected. If selection in makes listbox is later reset (set to 'Select Make') then models listbox becomes disabled again AND its selection is reset as well (to 'Select Model'). Makes are retrieved as resource while models are just hard-coded.

Makes JSON:

[
{"code": "0", "name": "Select Make"},
{"code": "1", "name": "Acura"},
{"code": "2", "name": "Audi"}
]

services.js:

angular.module('makeServices', ['ngResource']).
factory('Make', function($resource){
    return $resource('makes.json', {}, {
        query: {method:'GET', isArray:true}
    });
});

HTML file:

<div ng:controller="MakeModelCtrl">
  <div>Make</div>
  <select id="makeListBox" 
      ng-model="make.selected" 
      ng-options="make.code as make.name for make in makes"
      ng-change="makeChanged(make.selected)">
  </select>

  <div>Model</div>
  <select id="modelListBox"
     ng-disabled="makeNotSelected"
     ng-model="model.selected"
     ng-options="model.code as model.name for model in models">
  </select>
</div>

controllers.js:

function MakeModelCtrl($scope)
{
    $scope.makeNotSelected = true;
    $scope.make = {selected: "0"};
    $scope.makes = Make.query({}, function (makes) {
         $scope.make = {selected: makes[0].code};
    });

    $scope.makeChanged = function(selectedMakeCode) {
        $scope.makeNotSelected = !selectedMakeCode;
        if ($scope.makeNotSelected)
        {
            $scope.model = {selected: "0"};
        }
    };

    $scope.models = [ 
      {code:"0", name:"Select Model"}, 
      {code:"1", name:"Model1"}, 
      {code:"2", name:"Model2"} 
    ];
    $scope.model = {selected: "0"};
}

Hope it makes sense and will help to somebody.

share|improve this answer
25  
Dear random user. While this question and it's answer are rather simple and uncomplicated, your organization of code into its proper and respective locations (controller, service, template, data) shows the elegance of AngularJS in it's simplest and default form. Awesome example. – Atticus May 23 '13 at 15:30
1  
Very useful example - thanks! :) – Thomas Bratt Jan 15 '14 at 15:59
1  
This is not how it is meant to be used. ng-model should point to another variable on your scope, not related with make. See the example in docs.angularjs.org/api/ng/directive/ngOptions – Dmitri Zaitsev Apr 24 '15 at 5:40
    
@DmitriZaitsev I think you're wrong, just because the angular docs example shows it the way you described doesn't mean that's the only way. Show us why you think it is not supposed to be used this way rather than rubbishing a great example for newbies. – Jesse Taylor Jun 4 '15 at 16:25
    
This should be the answer. – Karl Morrison Jan 14 '16 at 12:09

For some reason Angular allows get's me confused. Their docs are pretty horrible on this. More good examples of variations would be welcome.

Anyway, I have a slight variation on Ben Lesh's answer.

My data collections looks like this:

items =
[
   { key:"AD",value:"Andorra" }
,  { key:"AI",value:"Anguilla" }
,  { key:"AO",value:"Angola" }
 ...etc..
]

Now this :

<select ng-model="countries" ng-options="item.key as item.value for item in items"></select>

still resulted in the options value to be the index (0,1,2...etc).

Adding Track By fixed it for me:

<select ng-model="blah" ng-options="item.value for item in items track by item.key"></select>

I reckon it happens more often that you want to add a array of objects into an select list, so I am going to remember this one!

Thanks all for assisting.

**** UPDATE **** Be aware that from Angular 1.4 you can't use ng-options anymore but you need to use ng-repeat on your option tag.

<select name="test">
   <option ng-repeat="item in items" value="{{item.key}}">{{item.value}}</option>
</select>
share|improve this answer
1  
This answer seems to be exactly what the question is asking for. Every other answer tells the reader not to worry what HTML is generated, but if the select element is in a form, I worry very much. Great answer! – Keith Apr 17 '15 at 4:52
3  
It should be pointed out that this stores the full selected object in the model, not just the key. If you want just the key in the model, you want to use the "item.key as item.value" version. This confused me for a while as I was hung up on what the HTML looked like, not the data that I wanted in the model, which is, for me, the important thing. – mhenry1384 Jul 8 '15 at 12:44
    
it could not select default value without using track by, your post remind me that and it's working now. thanks for inspiring – Ateş Danış Feb 29 '16 at 20:53
    
@mhenry1384 Yes you are right, about it storing the whole object. I actually like that feature because it gives you access to more than just the ID (if you need it.). Works well for me when I populate lists witha mongo collection and I need some property from the selected item. – Mattijs Feb 29 '16 at 23:09
1  
And how can we detect changes with "ng-change" inside option ? – Kwnstantinos Natsios Oct 24 '16 at 11:04

The question is already answered (BTW, really good and comprehensive answer provided by Ben), but I would like to add another element for completeness, which may be also very handy.

In the example suggested by Ben:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

a following ngOptions form has been used: select as label for value in array.

Label is an expression, which result will be the label for <option> element. In that case you can perform certain string concatenations, in order to have more complex option labels

Examples:

  • ng-options="item.ID as item.Title + ' - ' + item.ID for item in items" gives you labels like Title - ID
  • ng-options="item.ID as item.Title + ' (' + item.Title.length + ')' for item in items" gives you labels like Title (X), where X is length of Title string.

You can also use filters e.g.

  • ng-options="item.ID as item.Title + ' (' + (item.Title | uppercase) + ')' for item in items" gives you labels like Title (TITLE), where Title value of Title property and TITLE is the same value but converted to uppercase characters.
  • ng-options="item.ID as item.Title + ' (' + (item.SomeDate | date) + ')' for item in items" gives you labels like Title (27 Sep 2015), if your model has a property SomeDate
share|improve this answer
    
Thanks for the extra examples! – Moses Machua Jun 16 '16 at 16:04

In Coffeescript:

#directive
app.directive('select2',->
        templateUrl: 'partials/select.html'
        restrict: 'E'
        transclude: 1
        replace: 1
        scope:
            options: '='
            model: '='
        link: (scope, el, atr)->
            el.bind 'change', ->
                console.log this.value
                scope.model = parseInt(this.value)
                console.log scope
                scope.$apply()
    )
<!--html partial-->
<select>
  <option ng-repeat='o in options'
          value='{{$index}}' ng-bind='o'></option>
</select>
<!--html usage-->
<select2 options='mnuOffline' model='offlinePage.toggle' ></select2>
<!--conclusion-->
<p>Sometimes its much easier to create your own directive..</p>
share|improve this answer
1  
Dont forget your radix for parseInt: http://davidwalsh.name/parseint-radix – GFoley83 Jul 9 '14 at 1:29

I highly recommend using Select2 (http://ivaynberg.github.io/select2/#basics) because it will handle this for you. There is even a directive for angular (https://github.com/angular-ui/ui-select2).

share|improve this answer
1  
Neat recommendation, probably better as a comment on the original post instead of an individual answer though. – jpierson Nov 11 '14 at 19:47

If you need custom title for each option, ng-options not applicable, use ng-repeat with option:

<select ng-model="myVariable">
  <option ng-repeat="item in items" 
          value="{{item.ID}}" 
          title="Custom title: {{item.Title}} [{{item.ID}}]">
       {{item.Title}}   
  </option>
</select>
share|improve this answer

Hope should works 4 you.

 <select class="form-control"
        ng-model="selectedOption"
        ng-options="option.name + ' (' + (option.price | currency:'USD$') + ')' for option in options">
    </select>

Freshers Jobs

Thanks!

share|improve this answer

Altually there is a pure angular solution developed by QuantumUI.

You can find more examples and documentations here

http://quantumui.org/

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.