ngOption model value 0 or false treated as 'not selected' after 1.3.0-rc.4 #9639
Description
Was not able to find this bug mentioned after a search.
Specific Bug Behavior
Beginning with 1.3.0-rc.5, and continuing into today's snapshot, when one of the values in an ngModel choice set is the integer 0 or the boolean false, Angular now assumes this value is equivalent to having made no selection.
This is not a 'falsy' evaluation issue. The bug manifestation does not correspond to falsy values:
-1
- truthy, no bug0
- falsy, bug1
- truthy, no bugNaN
- falsy, no bugtrue
- truthy, no bugfalse
- falsy, bugundefined
- falsy, no bugnull
- falsy, no bug"1"
- truthy, no bug""
- falsy, no bug (select correctly chooses the new option with empty string value)
Examples
The code in the following two Plunkrs is identical, except for the Angular version.
Correct behavior - Model value of empty string is reflected in the 'choose' option being visually selected at load time.
Angular 1.3.0-rc.4
http://plnkr.co/edit/OUfDk8mAneJ4pO3pwxbC?p=preview
Incorrect behavior - Model value of empty string is still stored as empty string, but the select tag visually shows the 'Zero' option being selected at load time, representing a state inconsistency between the visual display and the underlying data. Furthermore, the 'Zero' option cannot be selected directly at this point, since the tag already thinks it is selected. The user must select some other option first before returning the real selection to the 'Zero' option.
Angular 1.3.0-rc.5:
http://plnkr.co/edit/RfsAKybKJIqic4B9yBVr?p=preview
Demonstrated Need
Server-side returns list of choices in a format like so:
[
{
"value": 0, // or false
"label": "Zero"
},
{
"value": 1,
"label": "One"
},
{
"value": 2,
"label": "Two"
}
]
This format was chosen because it
- Preserves ordering
- Allows the server to specify the database-relevant value
- Provides a human readable label without the client having to know every possible option in advance
Manifestation Code
<select ng-model="p.value" ng-options="c.value as c.label for c in p.choices">
<option value="">-- choose --</option>
</select>