Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

ng-model boolean value binding behaviour between jQuery and jqLite (ng-value with option problem) #6297

Closed
chatellier opened this issue Feb 17, 2014 · 15 comments

Comments

@chatellier
Copy link

Hi,

We are using following code to bind ng-model on boolean value:

    <select ng-model="filter.active">
        <option value=""/>
        <option value="true">True selected</option>
        <option value="false">False selected</option>
    </select>

Here is a fiddle explaining different behaviour if jquery is present or is not present on page:
working : http://jsfiddle.net/8byx5/
broken with jquery : http://jsfiddle.net/8byx5/1/

What do you think about this behaviour ?

@borodean
Copy link

Works exactly the same for me.
Chrome/34.0.1844.2 @ Windown 8.1

@chatellier
Copy link
Author

Tested on: Chromium 32/Firefox 27@ Linux and Chrome 30 @ Windows Vista. Still broken.
In the second fiddle, there is no default selection in select element.

@tbosch tbosch self-assigned this Feb 18, 2014
@tbosch
Copy link
Contributor

tbosch commented Feb 18, 2014

Actually,
the version without angular is broken, as the value attribute should be interpreted as a string. See this jsfiddle http://jsfiddle.net/SegcL/ where is used true1 and false1 as value.

@tbosch tbosch added this to the Backlog milestone Feb 18, 2014
@tbosch tbosch removed their assignment Feb 18, 2014
@chatellier
Copy link
Author

So my code is wrong even if it is working with only angular (without jquery) ?

@tbosch
Copy link
Contributor

tbosch commented Feb 20, 2014

No,
your code is correct!
I mean that the jQuery version works as intended, but the Angular only version does not.

@otaviosoares
Copy link

+1

@arkarkark
Copy link

+1 this is driving me nuts.

even when I use ng-value="true"

if my model has a value of true or false (the booleans) then angular inserts a blank value and inspecting it with the chrome inspector yields this:

<option value=​"? boolean:​false ?">​</option>​

of course you can't set an ng-value of "boolean:false"

I made a little fiddle to show off the problem clearly.
http://jsfiddle.net/arky/4gUmx/

the best option seems to be to use value= but then to accept both true and "true" as boolean

EDIT by @mzgol: your code was invisible so I wrapped it in code marks. I hope that's ok by you!

@kennardconsulting
Copy link

+1

@btford btford removed the gh: issue label Aug 20, 2014
@ghost
Copy link

ghost commented Sep 29, 2014

+1

@ghost
Copy link

ghost commented Sep 29, 2014

I "solved" this problem using directive.
Code with jquery: http://jsfiddle.net/ypdweq1r/

@tbosch tbosch self-assigned this Oct 3, 2014
@tbosch tbosch removed this from the Backlog milestone Nov 7, 2014
@tbosch tbosch removed their assignment Nov 7, 2014
@petebacondarwin
Copy link
Contributor

So you can't use ng-value with <option> if you want to compare with something that is not a string.
The ? boolean : false ? is just the way that the select directive renders the "unknown" option - the boolean : false is the hash key of the value of the ngModel.

We ought to fix this if possible, or at least make it clearer. You can make some progress using value and a custom boolean directive:

http://plnkr.co/edit/7sJoSlwgaEUBT45sqdgD?p=preview

@petebacondarwin petebacondarwin added this to the 1.3.x milestone Nov 11, 2014
@brandonburkett
Copy link

Just ran into this today and it wasn't until I inspected the element that I saw the extra "? boolean : false ?" select option.

@petebacondarwin
Copy link
Contributor

We need to work on getting ngValue working for the select directive (including with ngRepeat. @Narretz and @matsko this is an area you might be interested in?

Can we discuss this at a forthcoming 1.x meeting?

@petebacondarwin petebacondarwin modified the milestones: 1.5.x - migration-facilitation, 1.3.x - superluminal-nudge Sep 9, 2015
@Narretz
Copy link
Contributor

Narretz commented Sep 9, 2015

We can talk about it, sure. Although since ngOptions works pretty well now I would like to limit cycles for this.

@Narretz Narretz changed the title ng-model boolean value binding behaviour between jQuery and jqLite ng-model boolean value binding behaviour between jQuery and jqLite (ng-value with option problem) Sep 14, 2015
Narretz added a commit to Narretz/angular.js that referenced this issue Feb 6, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not follow any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when option are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Closes angular#9842
Closes angular#6297
@Narretz
Copy link
Contributor

Narretz commented Feb 6, 2016

I have a PR for that: #13962 13962

Narretz added a commit to Narretz/angular.js that referenced this issue May 17, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
Narretz added a commit to Narretz/angular.js that referenced this issue May 17, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this issue May 30, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
Narretz added a commit to Narretz/angular.js that referenced this issue Jun 1, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this issue Jun 17, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
Narretz added a commit to Narretz/angular.js that referenced this issue Jun 20, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
Narretz added a commit to Narretz/angular.js that referenced this issue Jun 30, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
Narretz added a commit to Narretz/angular.js that referenced this issue Jul 1, 2016
select elements with ngModel will now set ngModel to option values added by ngValue.
This allows setting values of any type (not only strings) without the use of ngOptions.

Interpolations inside attributes can only be strings, but the ngValue directive uses attrs.$set,
which does not have any type restriction. Any $observe on the value attribute will therefore receive
the original value (result of ngValue expression). However, when a user selects an option, the browser
sets the select value to the actual option's value attribute, which is still always a string.
For that reason, when options are added by ngValue, we set the hashed value of the original value in
the value attribute and store the actual value in an extra map. When the select value changes, we
read access the actual value via the hashed select value.

Since we only use a hashed value for ngValue, we will have extra checks for the hashed values:
- when options are read, for both single and multiple select
- when options are written, for multiple select

I don't expect this to have a performance impact, but it should be kept in mind.

Closes angular#9842
Closes angular#6297

BREAKING CHANGE:

`<option>` elements added to `<select ng-model>` via `ngValue` now add their values in hash form, i.e.
`<option ng-value="myString">` becomes `<option ng-value="myString" value="string:myString">`.

This is done to support binding options with values of any type to selects.

This should rarely affect applications, as the values of options are usually not relevant to the
application logic, but it's possible that option values are checked in tests.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants