How to set the initial selected value of a select element using Angular.JS ng-options & track by

I have been doing Angular.JS in production projects for months, that it did surprise me recently how I haven’t used drop-downs in it. Well, I mean how I haven’t used them enough to get into several problems I had in my current project, and other friends at the same office had in their project as well.

To save you the pain I went through, I’ll list some problems and solutions here, and then give you a video that shows going through all of them ans the thought process that led to the solutions.

Initial selection

Assuming someObject in the model has the same properties and values as someObject in the objectList, it will still not be selected.

It’ll only be selected if someObject was actually one of the objects in objectList, like objectList[0] or whatever. Otherwise, Angular.JS will insert an empty option tag with no value or text and select that.

Root Cause

Angular.JS uses native JavaScript comparison for comparing the objects. In JavaScript, unrelated to Angular.JS or anything, comparing objects (object literals) is “by reference”, so it doesn’t factor the similarity of the objects. Only checks if the two references compared point to the same object in memory or not.


An un-documented (AFAIK) feature in ng-options is that you can use some bits from the ng-repeat directive with it, like track by. This allows us to choose some property as the comparison key.

If the key property is a simple type, like Number or string, JavaScript will consider it equal to any other object that has the same value, so we don’t have to use the same objects.

Invalid Value Sent On Server-Side Submit

When Angular.JS writes the <option> tags from an ng-options directive pointing to an array, the value of the option is always the index of the element it maps to in the array. This is not important if you process the selection on client side because you only deal with the result of ng-model anyway, you can use this later to create an AJAX request or whatever.

However, if you intend to submit the form using a normal server submission, and only use Angular.JS for say validation or managing complex form interaction (client-side tables containing sub-items with add/remove/sort for example), this may be a road blocker to using Angular.

Root Cause

By default Angular.JS uses the index of the array to track which object maps to which <option> element.


Similar to the previous problem, use the track by syntax. Angular.JS will use the track by property value as the <option>‘s value. Most of the time your tracked property is the key property you want to send to the server anyway, so, this should be good enough.

Simple Properties Scenario When Combined With Server-Side Submit

Let’s say you want something as simple as this:

This syntax will work very well, if you only use this value from JavaScript, you are all set. But if you plan to send it directly to the server (a normal non-AJAX form submit), you’ll want to consider using the track by syntax, like track by

However, if you do this, you’ll notice that the select is no longer usable. No initial selection, and changing selection although updates the model, it does not show the new selected value.

Root Cause

The track by syntax expects an object, with the property you use to track. It does not honor the key part used in the key as text syntax (which in our example is as g.text), so, it wants the ng-model to point to an object with the tracked property, it cannot be the key itself directly.


I didn’t call this a solution, because it’s pretty much a hack.

We created a new property (which I liked to prefix with _ to show it doesn’t normally belong to the model object), initialized it to a new object that contains only our key property id set to the original simple value genderId, and then used that as the model (as in ng-model).

We created and assigned the property in ng-init, then synchronized the changes to the simple property via ng-change. This allows the code everywhere else in the application (like the controller, or other parts of the markup) to only interact with the property we want (genderId in this example), without knowing about our hack. This makes things a bit cleaner, although it still remains a hack rather than a solution.

You can view an example of using this hack here.

Adding extra selection items to the dropdown

One thing you notice if you are affected by the “initial selection” problem, is that the empty <option> tag that Angular.JS adds when it can’t match the ng-model to the array from ng-options disappears when the use changes their selection. We have gone through how to avoid showing the empty option by mistake already.

But if you do want to have that option, it’s easy, just, um, add it!


If you are using Angular 1.4+, check the much smaller 2nd part of this article, about how to use track by correctly.
Using track by correctly with Angular 1.4 select ng-options – Why can’t I select this option?

The Video

If you want to dig these problems really deep and see what they look like in action, and what was the thought process for solving them like and in some cases other possible solutions, I have put all this in a (rather long) video here:

Share With Friends:

P.S. Please help me out by checking this offer, then look below it for a special gift

Your Offer

Your Gift

As a bonus for coming here, I'm giving away a free newsletter for web developers that you can sign up for from here.
It's not an anything-and-everything link list. It's thoughtfully collected picks of articles and tools, that focus on Angular 2, ASP.NET 5, and other fullstack developer needs.

  • Fabian Lopez

    thanks so much that “hack” of yours just saved me a lot of time

  • Aman Jain

    Hi, I had gone through your detailed explanation about the nuances of the select element in Angular JS and also went through the video more than once. It was extremely helpful to understand how the Angular behaves. I have a similar problem with the select but in a bit different scenario :

    In my case, I open a modal window from the main home page, then on the modal window I have a lengthy form to submit in which there are multiple drop-down controls. I tried all possible ways that you had explained in the video, but it just does not seem to be working no matter what I have tried. It’s been more than a day that I am struggling with that and have posted my questions on various other sites but no answers till now. Could you please give me some pointers in my case ? Or if would need the code, then I can paste that here. Please let me know.

  • Pingback: AngularJS-Learning | Nisar Khan()

  • Computer Project

    Thanks to your article I solved the annoying problem of the blank option.
    At the moment, I’m stuck on saving the form whit the option selected. Could you take a look at my code? . Thank you.

    • @Meligy

      I think you need to change your ng-init to refer to the item of the list you want by default.
      For example: `ng-init=”anasubject.sbjType = types[0]”`

      Sample plunk

      • Computer Project

        Thanks a lot that solve my issue. This is my first big project in Angular.js and I very surprised how is it easy to make a CRUD app with few code line(I came from years of Icefaces/Primefaces development).
        However now I’m consider the idea to adopt the angular-kendo-ui in my project.

  • aradul

    Hi, what about ng-options with filter? – blank option again.

  • Laggel

    I literrally love you!! XD Thanks!

  • Pingback: Some notes on <select> and ng-options | angularnotes()

  • Jakub


    Thank you so much for “Initial selection” solution ! I just started using Angular and that blocked me for entire day, I was browsing documentation. blogs, stack overflow and no one gave this advices but you !

  • Rebel Sanders

    I’m new to angularjs and found your article very informative. However, when I tried to apply your techniques, I could not get them to work.

    I posted a question here.

    Here is the newest fiddle Any suggestions? Thanks in advance.

  • vasanth

    what IDE you are using?

    • moncef khoulfi

      i think it’s visual studio

      • @Meligy

        Yes, it’s Visual Studio 2013.

        You can download a free version (really good one) called Visual Studio Express for Web, which you can download from

  • Noel da Costa

    Have you raised an issue on the angularjs github repository for this? If so please point it out so that we can follow.

  • diegoRomero89

    Great post about select and ng-options. I went through hell just trying to render my option via ng-options, just to notice later that if you don’t specify a model it wont work.

  • moncef khoulfi

    Thank you, helped me solved some problems.

  • Pingback: Common Problems (And Solutions) When Using Sele...()

  • Muss

    Thank you very much for the first trick ! i was loopin trought object and reaffecting one from the list… very nice trick should be in the documentation of angular because it’s the first way how people will use select.

  • coder1991

    I also had very big problems with auto selection in combobox from my service. The logic in my app is very complex because of using many services, watches, directives etc. Thank you very much for this article, great video and explanations, especially with “track by” feature – it helped me a lot! :)

  • Buddy

    I can’t get the initial selection to work. My model ojbect looks like this:

    $scope.itemsPerPage = { value: “10”, text: “” };

    the data for the select looks like this:

    $scope.pagemodel = {
    “itemsperpage”: [
    {“text”: “View All”, “value”: “-1”},
    {“text”: “10 items per page”, “value”: “10”},
    {“text”: “15 items per page”, “value”: “15”},
    {“text”: “20 items per page”, “value”: “20”},
    {“text”: “25 items per page”, “value”: “25”}

    My select element looks like this:

    The result is that the item “View All” is what’s shown intially when I want the “10 Items per page” item shown. What am I doing wrong?

    FYI, I can’t set the text property value in the itemsPerPage model object becuause the items come from a localized data store the text is not always english.

    • Buddy

      I changed the select element to this

      and changed the $scope.itemsPerPage to this

      $scope.itemsPerPage = “10”;

      and it worked. Funny thing is, I swear I had tried this before.

  • Juan Carlos Espinoza

    That “track by” did the trick, thank you!

  • Alan

    Thank you thank you thank you!!!!!!!!!!!!!!!!!!!!

  • Leandro Daldegam

    Thank you! Was wondering how the automatic selection of the model when the webservice return the recorded on the database option. “track by” saved my life! :D

  • Latentcd

    Thank you for the tips!

  • Pingback: How could you become zero to hero in AngularJS? | Milap Bhojak()

  • Pingback: How to: How to set value property in angularjs ng-options? | SevenNet()

  • Samir Uppaluru

    Thanks! The hack at the end saved me from much frustration.

  • Hasan Siddiqov

    Thank You. Really great explanation. Helped me a lot for both development and understanding the framework itself.

  • Thomas’

    Thanks for pointing out the “track by” option. Helped me a lot!

  • Sean

    THANK YOU SO VERY MUCH for the 1st solution/example – using ‘track by’ in ng-options to eliminate the blank default value in a select box.


    Very useful information. Thank you very much

  • mrwillo

    Thanks Meligy. You saved my time.

  • Velmurugan Pousel

    awesome….you save my day….thanks

  • Saúl Darío Buendía Córdova

    What if the object selected at dropdown A includes the options for a second (child/nested/cascading) dropdown B? Since we’re setting a dummy/mock object at ng-init, it doesn’t populates dropdown B options until a different item is selected at dropdown A and ng-change is triggered. Please advise, I like this hack but need to implement nested/cascading dropdowns.

    • @Meligy

      In this case, instead of the dummy object, you can assign it to the result of a function call.

      You can create a function that takes the ID, looks in the list for the object that has the passed ID, and returns the matched actual object. Depending on your situation you might want to send the list itself to the function as well

  • BeginnerBaby

    Hello Mr.@Meligy could you pls help me to resolve the following issue please..

    i want to create folder/directory automatically, whenever the user upload his/her image file from their system.

    it should saved in server system in particular folder which should created automatically for each and every uploads with auto generated ID/ name for folders. well am okay with Javascript code also, but it could be if it is in AngularJs

    if it is possible means. please share the codes.

    Thanks a lot in advance

  • Pingback: Angular JS - JS | Pearltrees()

  • Pingback: Using track by correctly with Angular 1.4 select ng-options – Why can’t I select this option? / GuruStop.NET By @Meligy (JavaScript & Web Dev)()

  • Pingback: How to use ng-options in angular where Label and value are same - dex page()

  • Pingback: AngularU, NPM 3, & Hosting Recommendations — Issue12 — Meligy’s AngularJS & Web Dev Goodies / GuruStop.NET By @Meligy (JavaScript & Web Dev)()

  • Sujoy Datta Choudhury

    amazing…was pulling my hair for the last couple of hours for this…:)

  • metric152

    This article really helped me figure out an issue trying to set the value of a select field.

  • Draex

    in ng-options in Simple Properties Scenario When Combined With Server-Side Submit I feel like instead of “ as gender.text for …” should only be “gender.text for”

  • David Ballester

    Thanks, man.

  • emanijeh

    Thank you. Very helpful!

  • Luciano Sousa

    This solution also save me.

    Thanks for share it.

  • Pingback: angularjs - How to use ng-options in angular where Label and value are same - CSS PHP()