Initializing select with AngularJS and ng-repeat

JavascriptAngularjs

Javascript Problem Overview


I'm trying to get select-box to start off with a pre-filled option using ng-repeat with AngularJS 1.1.5. Instead the select always starts out with nothing selected. It also has an empty option, which I don't want. I think that there is a side effect of nothing being selected.

I can get this working using ng-options instead of ng-repeat, but I want to use ng-repeat for this case. Although my narrowed down example doesn't show it, I also want to set the title attribute of each option, and there is no way to do that using ng-options, as far as I know.

I don't think this is related to the common AngularJs scope/prototypical inheritance issue. At least I don't see anything obvious when inspecting in Batarang. Plus, when you pick an option in the select with the UI, the model does update correctly.

Here's the HTML:

<body ng-app ng-controller="AppCtrl">
    <div>
        Operator is: {{filterCondition.operator}}
    </div>
    <select ng-model="filterCondition.operator">
       <option 
           ng-repeat="operator in operators" 
           value="{{operator.value}}"
       >
           {{operator.displayName}}
       </option>
    </select>
</body>

And the JavaScript:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }
    
    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]
}

JS Fiddle for this : http://jsfiddle.net/coverbeck/FxM3B/2/

Javascript Solutions


Solution 1 - Javascript

OK. If you don't want to use the correct way ng-options, you can add ng-selected attribute with a condition check logic for the option directive to to make the pre-select work.

<select ng-model="filterCondition.operator">
    <option ng-selected="{{operator.value == filterCondition.operator}}"
            ng-repeat="operator in operators"
            value="{{operator.value}}">
      {{operator.displayName}}
    </option>
</select>

Working Demo

Solution 2 - Javascript

For the select tag, angular provides the ng-options directive. It gives you the specific framework to set up options and set a default. Here is the updated fiddle using ng-options that works as expected: http://jsfiddle.net/FxM3B/4/

Updated HTML (code stays the same)

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.value as operator.displayName for operator in operators">
</select>
</body>

Solution 3 - Javascript

The fact that angular is injecting an empty option element to the select is that the model object binded to it by default comes with an empty value in when initialized.

If you want to select a default option then you can probably can set it on the scope in the controller

$scope.filterCondition.operator = "your value here";

If you want to an empty option placeholder, this works for me

<select ng-model="filterCondition.operator" ng-options="operator.id as operator.name for operator in operators">
  <option value="">Choose Operator</option>
</select>

Solution 4 - Javascript

Thanks to TheSharpieOne for pointing out the ng-selected option. If that had been posted as an answer rather than as a comment, I would have made that the correct answer.

Here's a working JSFiddle: http://jsfiddle.net/coverbeck/FxM3B/5/.

I also updated the fiddle to use the title attribute, which I had left out in my original post, since it wasn't the cause of the problem (but it is the reason I want to use ng-repeat instead of ng-options).

HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator">
   <option ng-repeat="operator in operators" title="{{operator.title}}" ng-selected="{{operator.value == filterCondition.operator}}" value="{{operator.value}}">{{operator.displayName}}</option>
</select>
</body>

JS:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }
    
    $scope.operators = [
        {value: 'eq', displayName: 'equals', title: 'The equals operator does blah, blah'},
        {value: 'neq', displayName: 'not equal', title: 'The not equals operator does yada yada'}
     ]
}

Solution 5 - Javascript

As suggested you need to use ng-options and unfortunately I believe you need to reference the array element for a default (unless the array is an array of strings).

http://jsfiddle.net/FxM3B/3/

The JavaScript:

function AppCtrl($scope) {

    
    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]
    
    $scope.filterCondition={
        operator: $scope.operators[0]
    }
}

The HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator.value}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.displayName for operator in operators">
</select>
</body>

Solution 6 - Javascript

If you are using md-select and ng-repeat ing md-option from angular material then you can add ng-model-options="{trackBy: '$value.id'}" to the md-select tag ash shown in this pen

Code:

<md-select ng-model="user" style="min-width: 200px;" ng-model-options="{trackBy: '$value.id'}">
  <md-select-label>{{ user ? user.name : 'Assign to user' }}</md-select-label>
  <md-option ng-value="user" ng-repeat="user in users">{{user.name}}</md-option>
</md-select>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCharles O.View Question on Stackoverflow
Solution 1 - Javascriptzs2020View Answer on Stackoverflow
Solution 2 - JavascriptJeremy LiknessView Answer on Stackoverflow
Solution 3 - JavascriptAmmaduView Answer on Stackoverflow
Solution 4 - JavascriptCharles O.View Answer on Stackoverflow
Solution 5 - JavascriptshaunhusainView Answer on Stackoverflow
Solution 6 - JavascriptJapheth Ongeri - inkalimevaView Answer on Stackoverflow