Closed RickStrahl closed 9 years ago
Is this a correct reproduction? http://plnkr.co/edit/k09Xh9xEgcXQBbKTkRdh So the select does not reflect the model?
The reason for this is that in 1.4 we test for exact equality in the select directive. If you have static options then the values of these options are strings. See http://plnkr.co/edit/KCM6Kz22sB5GVcPvOZgT?p=preview
You can provide a simple directive to convert the value from number to string and back between the model and view: http://plnkr.co/edit/BnNkVENvNYyArbRjVaov?p=preview
We should probably highlight this in the docs for select
if it is not already.
While I think that this makes sense conceptually and probably for performance as well, I think this has a terrible usability aspect. I would imagine that this is a fairly common scenario that needs to be addressed and there's no intuitive discovery of this behavior until it fails. If you're new and starting out you're not going to make the connection that you have a type conversion problem.
Even the solution of requiring a custom directive to make this work seems heavy handed. Shouldn't there be something built in to provide these types of conversions for you more easily without having to create a component?
I don't want to derail this issue - the solution given is straight forward enough for me to fix and I can live with that. Thanks for pointing to the source of the issue and the solution!
But I think in the grander scheme of things this should be thought over going forward (not sure how this will be handled in 2.0).
We previously compared the model and attribute value with ==
which did type conversion. However, did caused false
to be equal to 0
for example. Also bad. The root problem is simply that HTML does only allow strings inside value attributes, so your integers become strings in the DOM. You can use ngOptions to remedy this problem.
A more pernicious issue with using ==
and implicit conversion is that on the way "out" of such a select your model would change from being a number to a string.
I updated the select
docs to highlight this issue and to provide a running example of using a custom conversion directive.
Thanks all. The docs and sample are definitely a good addition.
I have a scenario that I am still unable to get to work, even with the directive: I have a set of enumerated values that I want to use for the options. It is unable to bind to get the initial value correctly, but if I put in the value directly for each enumerated value it works correctly.
<select ng-model="vm.frameworkContext.frameworkViewType" convert-to-number>
<option value="{{vm.enums.FrameworkViewType.STATE_FRAMEWORK_ONLY}}">
State Framework Only
</option>
<option value="{{vm.enums.FrameworkViewType.INSTRUCTION_FRAMEWORK_ONLY}}">
Instructional Framework Only
</option>
<option value="{{vm.enums.FrameworkViewType.STATE_FRAMEWORK_DEFAULT}}">
State Framework Default
</option>
<option value="{{vm.enums.FrameworkViewType.INSTRUCTIONAL_FRAMEWORK_DEFAULT}}">
Instructional Framework Default
</option>
</select>
where
vm.enums.FrameworkViewType: {
UNDEFINED: 0,
STATE_FRAMEWORK_ONLY: 1,
STATE_FRAMEWORK_DEFAULT: 2,
INSTRUCTIONAL_FRAMEWORK_DEFAULT: 3,
INSTRUCTION_FRAMEWORK_ONLY: 4
}
@annechinn, it seems to be working as expected. If you experience any issues, please open a new issue, providing all necessary info to reproduce the problem (preferrably a live demo of the bug, using CodePen, Plnkr, etc).
@annechinn I think your problem might be that option values are strings, while your enum values are integers. This is precisely the problem discussed here and now described in the select
.
I created the plunker and found that it is reproducible in 1.3, but fixed in 1.4, so I will not create a new issue. In case you're interested, i've provided a link to the plunker to demontrate that it was broken in 1,3, even with the convert-to-number directive.
http://plnkr.co/edit/A5onypmeEm8xUzSDdpG1?p=preview
On Wed, Oct 28, 2015 at 2:38 AM, Pete Bacon Darwin <notifications@github.com
wrote:
@annechinn https://github.com/annechinn I think you problem might be that option values are strings, while your enum values are integers. This is precisely the problem discussed here and now described in the select.
— Reply to this email directly or view it on GitHub https://github.com/angular/angular.js/issues/11890#issuecomment-151780334 .
@annechinn, the issue demonstrated in your plnkr is not the same (hence the convertToNumber
directive does not solve it). It is a timing problem (due to interpolations in value
attributes) and can be reproduced even with string model-values.
It can be worked around by initializing your model values in a timeout.
I don't think such kind of bugs are getting fixed on v1.3.x
(since it's an old version).
I understand why === is much more better-er than ==, but this causes all sorts of issues when trying to bind to an object (as I am currently fighting with). We have an object barfing out as { boundValue: 69 }
yet with the changes as described above, I'm going to need to do something equivalent to this: { boundValue: 69, boundValueStr: "69" }
... really!?
How about due to the new use of === and the fact that the right-hand side of this equation is always a string thanks to the HTML DOM, how about we force the left-hand side to be a string as well? Or at least give us the option to do so without some hack-y secondary directive (which I've still not gotten to work right in our case, by the way).
@campbeln The value attribute in selects can only be a string, so when you have numbers you should use the ngOptions directive. Why the directive workaround doesn't work in your case is hard to say, but that's a question better asked on Stackoverflow etc. Lastly, if you have an idea how to improve the directive, opening a new issue is probably the better idea.
@Narretz ng-options
doesn't bind it either in our tests!? Besides it seems boneheaded to require all SELECT
values to be strings when the right is always a string. Then we devs will be required to coerce all API values to strings if we need to use a SELECT?!
If ng Options doesn't bind satisfactorily please provide a minimal demo in a plnkr.co or similar and I'll have a look.
Raised new issue here - https://github.com/angular/angular.js/issues/13955
You can't use ng-options
if you're doing something stupid like returning a new array of objects from a function call (e.g. ng-options='item in myFunct()'
). Then you try and use track by
but that cannot be used with select
s (as in the horrible ng-options version, not HTML DOM objects). What _may_ get us around it is to cache the results from the first call so that all references are the same and we won't need track by
, but I'm not sure that will work in all cases in our system.
I have a list of static values that are bound to a list and I'm trying to get the list to display the value from the model.
The model value is an integer:
Then in the html I'm binding this value to a dropdown list of static values:
This worked fine in v1.3 but in 1.4 the list comes back with no selection. Or, more specifically it has a selection of an injected element: