Search code examples
javascriptangularjsangularjs-select

AngularJS Select Options Preselection


I'v some problems with preselection of a select-input in angularJS. The select-box get filled by an array.

<select class="form-control" 
ng-model="userCtrl.selected_country" 
ng-options="country.name for country in userCtrl.available_countries track by country.id">
</select>

e.g. a selected country is filled with an ID (which I get by an API).

userCtrl.selected_country = 4;

But it won't work. I also have tried to do it with options and ng-selected.

<option ng-repeat="country in userCtrl.available_countries"
ng-selected="{{ country.id == userCtrl.selected_country }}"
value="{{ country.id }}">
{{ country.name }}
</option>

Why I can't make the selection like this? THIS "works", in the source code I see at the correct option selected="true" - but on the view you don't see it... very strange.

My "solution" now is, that I fill my ng-model with the correct value of the source-array "available_countries". Unnecessary many steps?!

  1. Load data (select fills) of API
  2. Load data (addresses) of API
  3. Manipulate all referenc-IDs (like country_id, state_id) to the select-fill-objects (for preselection)
  4. User editing happens => user clicks update
  5. Change all select-fill-objects back to the reference-id
  6. Save addresses now
  7. repeat step 3

3., 5. and 7. are unnecessary if I could preselect just with an number. Is this anyhow possible?

Thanks for help :-) Stefan


Solution

  • Extending @zeroglagL answer a bit.

    In your example ng-options directive is used in a way telling AngularJS that both ng-model AND option should be objects with the same structure:

    // JSON representation of userCtrl.selected_country is an object
    {
        name: "Poland",
        id: 1 
    }
    
    // JSON representation of userCtrl.available_countries in an array of objects
    [
    {
        name: "Poland",
        id: 1 
    }
    {
        name: "USA",
        id: 2
    }
    ]
    

    So basically when you use:

    ng-options="country.name for country in userCtrl.available_countries track by country.id"
    

    You tell AngularJS to create option object for each country in the userCtrl.available_countries array, with country.name as a label and country.id as a value of each option. AngularJS will also assume that ng-model is going to be an object and will "bind" options with a model by id property of both objects.

    So you have to build your ng-model the way I described above.

    Or you can use ng-options in other way (as stated by @zeroglagL):

    ng-options="country.id as country.name for country in userCtrl.available_countries"
    

    In this approach you tell AngularJS to treat both options and ng-model as scalar ids only (and not objects). There is no need to "bind" objects by their ids anymore because AngularJS will simply compare integer values when preselecting option. This way userCtrl.available_countries can be in fact array of objects, but ng-model value (after selection or preselection) will only contain id