5

I have a ng-options list defined with a HTML select element such as:

<select
    required="required"
    ng-model="vm.selectedOption"
    ng-options="item.name as item.label for item in vm.options">

    <option value="">Select an option</option>
</select>

This however results in the following HTML:

<option value="string:VALUE" label="Option Name">Option Name</option>

I am using Angular version 1.4.8, does anyone have a solution how to solve the string: issue or at least can explain to me why this is occurring?

The vm.options array looks like this:

[
  {
    "name": "INFILL_AUTOMATIC",
    "label": "Automatic"
  },
  {
    "name": "INFILL_GRID",
    "label": "Grid"
  }
]

//EDIT:

When logging vm.selectedOption I just see the correct value. So the ng-model does in fact have the correct value. But why is Angular giving the default value then this prefix, is it using this prefix to define the "type" for the ng-model or something?

Bouke
  • 660
  • 2
  • 7
  • 22
  • 1
    Try to output `vm.selectedOption` into the view, I suspect that nothing is wrong with what you see – Alon Eitan Jan 19 '16 at 18:33
  • Possible duplicate of [Angular adds strange options into select element when setting model value](http://stackoverflow.com/questions/16783294/angular-adds-strange-options-into-select-element-when-setting-model-value) – mic4ael Jan 19 '16 at 18:52
  • @mic4ael I saw that post as well but the suggestion there was to use `ng-options`, which I am already using instead of `ng-repeat`. – Bouke Jan 19 '16 at 18:54

2 Answers2

8

This behavior is documented in the angular changelogs, as a breaking change for Angular 1.4-beta.0. https://github.com/angular/angular.js/blob/master/CHANGELOG.md#breaking-changes-17

Basically, in order to preserve duplicate checking within ng-options, if a list of primitive values are supplied to ng-options, the value's type is prepended to the value in order to create a unique hash key to track (this differs from earlier versions of angular, which would track by the index or the key of the item in the collection).

In practice, this should not affect most usages of ng-options. If it is important for you to preserve the value parameter of the dropdown, you can use the track by parameter in ng-options in order to provide an alternate key to be used for duplicate tracking.

Note that this differs from ng-repeat, in that ng-repeat cannot generate a surrogate key using this method, since it would affect the behavior of the repeated elements. Therefore if a duplicated list is passed to ng-repeat without a track by clause, ng-repeat will produce an error and not render the items, where ng-options is able to render the list.

Claies
  • 22,124
  • 4
  • 53
  • 77
  • Thanks @claies that explains it! – Bouke Jan 19 '16 at 21:24
  • 2
    Using "track by" causes the drop down to lose default value auto select. like if you ng-model="modelId" and model already has a value, it's not select by default. How do you fix that? – TatiOverflow Dec 02 '17 at 00:40
  • @TatiOverflow default values definitely should work; you might want to open a new question with a [mcve] showing how it isn’t working, and reference this question if you believe it is relevant. – Claies Dec 02 '17 at 03:03
1

Here is the working Plunker

And JS:

    <select ng-model="template"    ng-options="c as (c.label + ' - ' + c.name) for c in options">
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396