Ryan Langton
Ryan Langton

Reputation: 6160

Angular ng-options broken 1.4+

Angular < 1.4 works with ng-options shown as such:

<select ng-options="option.value as option.label for option in options" ng-model="selectedValue">

With the following array of options:

[{ value:"4_220588",label:"dropdown 1-test value 1"},{value:"4_220589",label:"dropdown 1-test value 2"}]

If you look at the resultant HTML is is as you would expect:

<select ng-options="option.value as option.label for option in options" ng-model="selectedValue" class="ng-pristine ng-valid ng-touched">
    <option value="" class="">-- SELECT ONE --</option>
    <option value="0" label="dropdown 1-test value 1">dropdown 1-test value 1</option>
    <option value="1" label="dropdown 1-test value 2">dropdown 1-test value 2</option>
</select>

As soon as you change the angular version to Angular 1.4+, the option value attribute get's messed up. Here is the output with the same ng-options using a newer version of angular:

<select ng-options="option.value as option.label for option in options" ng-model="selectedValue" class="ng-pristine ng-valid ng-empty ng-touched">
    <option value="" class="" selected="selected">-- SELECT ONE --</option>
    <option label="dropdown 1-test value 1" value="string:4_220588">dropdown 1-test value 1</option>
    <option label="dropdown 1-test value 2" value="string:4_220589">dropdown 1-test value 2</option>
</select>

What is the solution to getting the value to show up still as the index of the array?

Here is the plnkr: http://plnkr.co/edit/3CTUI9b9ntTGWhXDNQI5?p=preview

Upvotes: 2

Views: 588

Answers (3)

Claies
Claies

Reputation: 22323

Your application logic should not be sensitive to the value attribute in the dropdown, because ng-model will set the model correctly regardless of what is output in the HTML. If you application logic does expect a specific format for this attribute, you have 3 ways to deal with this breaking change.

  1. Use ng-repeat instead of ng-options. This is the least recommended option, as it changes the way the select lists work significantly.
  2. Use a track by clause to enforce the key format that you are expecting, i.e. option.value as option.label for option in options track by option.value. This presumes that option.value exists and is the value you wish to represent. http://plnkr.co/edit/TSXfkpf1lhsE9QYa2NAc?p=preview
  3. Change your application logic to expect the hashkey instead, or preferably correct the logic so that it only relies upon ng-model.

Upvotes: 1

Justin Herter
Justin Herter

Reputation: 590

This should do the trick:

<select ng-options="index as option.label for (index, option) in options2" ng-model="vm.selectedValue">
    <option value="">-- SELECT ONE --</option>
  </select>

On render the value of the selected option would be string:index but will output the desired value without the type included. Here is your edited plunker with the expected result in the Selected Value:

Plunker

Upvotes: 0

ohboy21
ohboy21

Reputation: 4319

One solution would be to use ng-repeat over the options.

<select ng-model="vm.selectedValue">
  <option value="" selected disabled>-- SELECT ONE --</option>
  <option ng-repeat="option in options" 
           value="$index" 
           ng-selected="option === vm.selectedValue">
        {{option.label}}
  </option>
</select>

Here is your updated Plunkr.

Upvotes: 0

Related Questions