Initial ng-model value not set in select

All we need is an easy explanation of the problem, so here it is.

I have an enum (I code using TypeScript):

export enum AddressType
{
    NotSet = 0,

    Home = 1,
    Work = 2,
    Headquarters = 3,

    Custom = -1,
}

Then in my controller I have a field named type, into which I set the initial value that should be selected in the select input (I set it to AddressType.Headquarters).

Finally, in my HTML I put the following:

<select ng-model="Ctrl.type" ng-options="addressType for addressType in Ctrl.getAddressTypes()"></select>

Everything seems to work fine except one thing: for some reason Angular does not select “3” (Headquarters) initially in the select after all bindings have been updated. Angular creates an extra option like this instead:

<option value="?" selected="selected"></option>

So for some reason Angular cannot figure the initial option to select in the combo.

If the user selects another option of the combo box, Ctrl.type is updated properly so the binding works fine for that part. Basically my problem is just that the option that should be selected initially is not selected as expected.

What am I missing here that is causing that problem?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Found the problem:

The array returned by Ctrl.getAddressTypes() was an array of strings:

["0", "1", "2", "3", "1"]

and what was stored in Ctrl.type was of type number.

AngularJS compares the array supplied to ng-options to the value supplied to ng-model using the ‘===’ operator. 3 does not equal to “3” in that case – that’s why it did not work.

Method 2

I often run into this when using number id’s. My way around this quirk is to add ''+ to convert it to string type:

<select ng-options="''+u.id as u.name for u in users"

Method 3

In a function if the below code is added and the same is called from the ng-init then the issue is also getting resolved. This will resolve the string comparison issue.

$scope.Ctrl.type = "" + $scope.Ctrl.type + "";

Method 4

I happens because you didn’t initiated selected value. Try to set init value with ng-init:

<select ng-model="Ctrl.type" 
       ng-options="addressType for addressType in Ctrl.getAddressTypes()"
       ng-init="Ctrl.type = ..."
       ></select>

See this Demo Fiddle where we have 2 combos with and without init value. You can see that one combo HTML seems like:

<select ng-model="selectedItem1"
 ng-options="selectedItem1.name as selectedItem1.name for selectedItem1 in values" class="ng-pristine ng-valid">
   <option value="?" selected="selected"></option>
   <option value="0">General</option>
   <option value="1">Super</option>
   <option value="2">Trial</option>
 </select>

The proper one:

<select ng-model="selectedItem" 
        ng-options="selectedItem.name as selectedItem.name for selectedItem in values" 
        ng-init="selectedItem = values[1].name" class="ng-pristine ng-valid">
   <option value="0">General</option>
   <option value="1" selected="selected">Super</option>
   <option value="2">Trial</option>
</select>

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply