-
Notifications
You must be signed in to change notification settings - Fork 27.4k
feat(input): constant exprs for ngTrueValue/ngFalseValue #5346
Conversation
Thanks for the PR!
If you need to make changes to your pull request, you can update the commit with Thanks again for your help! |
I'm sorry, but I wasn't able to verify your CLA signature. CLA signature is required for any code contributions to AngularJS. Please sign our CLA and ensure that the CLA signature email address and the email address in this PR's commits match. If you signed the CLA as a corporation, please let me know the company's name. Thanks a bunch! PS: If you signed the CLA in the past then most likely the email addresses don't match. Please sign the CLA again or update the email address in the commit of this PR. |
CLA signature verified! Thank you! Someone from the team will now triage your PR and it will be processed based on the determined priority (doc updates and fixes with tests are prioritized over other changes). |
@@ -810,14 +819,14 @@ function checkboxInputType(scope, element, attr, ctrl) { | |||
</doc:scenario> | |||
</doc:example> | |||
*/ | |||
var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { | |||
var inputDirective = ['$browser', '$sniffer', '$injector', function($browser, $sniffer, $injector) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not inject $parse directly? I think that would be better. try to avoid direct interactions with injector whenever possible. otherwise the dependencies become hard to follow and you end up using service location rather than dependency injection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking was, different input types might need to inject different things ($interpolate / $parse / $whatever) in the future... But if it's okay to pile on extra things, then there's probably no harm in just injecting it directly.
This looks good to me, except for one thing - have you thought about what should happen when someone points ng-true-value to a path like |
I guess my original thinking was, constants would be good because you wouldn't expect them to be re-evaluated each time, but I suppose there's no reason it would have to be constant |
Changed it to not throw away non-constant expressions, it throws away undefined when the expression is not "undefined" now... This is really all to avoid a breaking change, it could be updated to just use the parsed value regardless though. |
expect(inputElm[0].checked).toBe(false); | ||
|
||
browserTrigger(inputElm, 'click'); | ||
expect(scope.value.num).toEqual(12345); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
toBe
you are missing a test for the |
If ngTrueValue / ngFalseValue are strings, they are evaluated as expressions. If the resulting value is undefined, and not the "undefined" constant, then it is treated as a string literal. Otherwise, the evaluated value is used. If no string expression is provided, then the default value remains true or false.
So I guess, regarding the other points you've mentioned, it comes down to: a) should getter be re-evaluated each time the formatter is run b) should deep equality check be used rather than === for a), checking only once is closer to the current implementation (but maybe that's not desirable), for b) if it's a really complicated object (which is probably an unlikely scenario for a checkbox), it will hurt --- but in most cases it should be short circuited by the identity equality check in To avoid the function call, an external |
This could also be related to #4970 |
How about adding an It might look a little ugly, but I'm thinking some sort of convention across directives for expressions that are "live" would make sense (e.g. |
@IgorMinar what do you think about @chrisirhc's suggestion? Since cdc4d48 landed, it might not cause code to inflate TOO much to have two implementations. But maybe two is too many |
Ping |
We should not add another set of attributes just to deal with expressions. I'd rather break this api to fix it since it's not a frequently used one. How about a compromise where we check if the expression is constant and if it is we'll go ahead with otherwise we throw an error saying that non-constant expressions are not currently supported? Alternatively we could support non-constants but we'd have to set up watches for ngTrueValue and ngFalseValue and update the checkbox state should the watch fire. This would mean that the checkbox would be controlled by 3 watches: ngModel, ngTrueValue and ngFalseValue. Which might cause some really odd behavior. |
what do you think about the changes I proposed? supporting non-constants should be trivial, supporting all expressions is more tricky but you can give it a shot (we'll need tests for the scenarios where true/false expression changes at runtime). I'm thinking that the trueValue comparison should always take a precedence over false value so if both true value and false value are the same, we should consider the checkbox to be checked. |
@IgorMinar so you're saying for 1.3 we should just break this and use parsed expressions? I can fix this up to do that and add some better tests
I think if trueValue===falseValue we should probably emit some kind of warning, because that doesn't seem like a sensible thing to do. Maybe a warning that could be compiled out in release builds if we ever get that working |
I can't see how we could preserve backwards compatibility here without introducing new attributes or magic that is going to burn people, both are only more confusing. wrt warning: we don't emit a warning today and you can set the trueValue and falseValue to the same string. I keep on going back and forth between supporting constants only vs supporting all expressions. What's your take on that? My thinking is that supporting constants would deal with 90% of use cases without the complexity associated with supporting full expressions. |
Supporting constants only, you gain the benefit of not having to watch the expression, but maybe bind-once is a better solution for that in 1.3, so maybe adding another $watch isn't so bad here. |
let's do constants only and throw an error for non-constants. one time binding is not going to help much because it's not so much the On Tue, Jul 1, 2014 at 1:49 PM, Caitlin Potter notifications@github.com
|
ngTrueValue and ngFalseValue now support parsed expressions which the parser determines to be constant values. BREAKING CHANGE: Previously, these attributes would always be treated as strings. However, they are now parsed as expressions, and will throw if an expression is non-constant. To convert non-constant strings into constant expressions, simply wrap them in an extra pair of quotes, like so: <input type="checkbox" ng-model="..." ng-true-value="'truthyValue'"> Closes angular#8041 Closes angular#5346 Closes angular#1199
Let's add two another directives, e.g.: |
@ZAYEC77 – I think this is an interesting idea, but I don't think it belongs in core. Still, if you want this feature, you can easily implement and publish it as a 3rd party module with npm or bower. |
If ngTrueValue / ngFalseValue are strings evaluating to constant expressions,
the constant value is used in place of the string value.
If the value is not a constant, its string value is used, as they were
previously.
If no string expression is provided, then the default value remains true or
false.
Fixes #1199