-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Added support for numerical ngTrueValue and ngFalseValue attributes #3251
Conversation
Suggested approach for supporting numerical true/false values in checkbox inputs.
PR Checklist (Minor Feature)
|
@simonsparks - thanks for making this PR. Can you take a look at the task list above. |
function typedValue(val, defaultVal) { | ||
return isString(val) | ||
? !isNaN(parseFloat(val)) && isFinite(val) | ||
? parseFloat(val) |
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.
Can this be done more concisely with:
return isString(val) ?
(isFinite(val) ? parseFloat(val) : val) :
defaultVal;
If it is a string and finite number (isFinite parses strings and returns false for NaN) then return the parsed number. Also isFinite is more choosy - for instance parseFloat will return 9 for "9/3", whereas isFinite will return false
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.
The approach committed I've used in the past based on this SO question: http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric
But I don't personally know if ordering isFinite() first will be sufficient to catch all cases where parseFloat might fail.
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.
Here are most, of the cases I could come up with:
isFinite(100) => true
isFinite(0) => true
isFinite(-100) => true
isFinite(1.3) => true
isFinite(1/0) => false
isFinite(NaN) => false
isFinite("100") => true
isFinite("-34.3") => true
isFinite(null) => true
isFinite(undefined) => false
isFinite("abc") => false
isFinite(1e3) => true
isFinite("1e3") => true
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.
Looking further, I noticed a suite of unit tests against various approaches: http://dl.dropboxusercontent.com/u/35146/js/tests/isNumber.html
and saw that isFinite(String(n)) passes empty strings and whitespace as valid numbers.
I'm guessing we could assume a use case where an empty string was desirable as a false value.
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.
Fair enough. But if you use your original version we should cache the
parsed value rather than running parseFloat twice
On 17 July 2013 14:04, Simon Sparks notifications@github.com wrote:
In src/ng/directive/input.js:
@@ -666,6 +663,13 @@ function checkboxInputType(scope, element, attr, ctrl) {
});
}+function typedValue(val, defaultVal) {
- return isString(val)
- ? !isNaN(parseFloat(val)) && isFinite(val)
? parseFloat(val)
Looking further, I noticed a suite of unit tests against various
approaches:
http://dl.dropboxusercontent.com/u/35146/js/tests/isNumber.html
and saw that isFinite(String(n)) passes empty strings and whitespace as
valid numbers.
I'm guessing we could assume a use case where an empty string was
desirable as a false value.—
Reply to this email directly or view it on GitHubhttps://github.com//pull/3251/files#r5241172
.
There is a potential breaking change, where the user may have wished to actually have a string but that string happens to be a number. I don't think this is really an issue because in reality the number will be serialized back to a string as needed. |
We also need a documentation update to explain this new behaviour. |
@petebacondarwin - no problem, hope it helps. CLA has been signed (Simon Sparks) and the PR message has been modified, let me know if that still needs improving. I did wonder about the potential breaking change you mentioned. I thought an extra attribute to express which way to interpret numbers was messy and I think you're probably right about serialization. Where would we need updated documentation for this change? Just the doc comments in input.js? |
@simonsparks - thanks for the quick response. Create a new commit with the doc update - yes in the comments input.js. We should probably add a qualified breaking change comment to this new commit explaining the small potential for problems if the developer was relying upon the "type" of the value to be a string, when it contains only numerals. I can squash the two commits together when we merge. In the meantime we ought to get another team member to review this. |
The place to update the docs is probably here: https://github.com/Sparks-Creative-Limited/angular.js/blob/0a2df367a1f1b3abb04d1912f4626e5a7b368c6e/src/ng/directive/input.js#L343 |
documentation update to convey support for both string and number values in ngTrueValue and ngFalseValue attributes
number parsing performance improvement and addition of further unit test cases
I have now refactored the number parsing algorithm to cache the intermediate float value for reuse, I have added some more unit tests to cover different string and number value scenarios, and I have included a breaking change notice in the PR message (not sure about the markup formatting there; I was trying to copy layout in the message conventions guide but it looks like it may need adjusting).
The previous angular.js build in the queue failed for the same reason. |
The build is now passing. |
Is this feature good to go now, or is there anything else I need to do? |
@simonsparks Thanks for the PR! After some deliberation, we've unfortunately decided not to merge this for a few reasons:
Still, we really appreciate the effort you put into the PR, and hope this doesn't discourage you from future contributions. Thanks! |
No problem Brian, |
Its not quite so easy if your DB stores integers and you can't (or are not willing) to make your local model pretend to be a string. Any news on the current progress of an official solution? Would be much appreciated! Until then, I guess we'll use a custom directive. |
feat(ng): support for numerical ngTrueValue and ngFalseValue attributes
Checkbox input fields may now be declared with numerical ng-true-value and ng-false-value settings.
The input's corresponding model will be interpreted as a number rather than a string representation.
Regular string configurations which do not parse as numbers will be treated as before.
BREAKING CHANGE: numeric values for ngTrueValue and ngFalseValue attributes are
now interpreted as numbers rather than their string representation. This may affect
cases where a string representation of a number is expected in a checkbox field's
associated model and the identity operator (===) is used for comparison.
To migrate the code, make comparisons with the numerical typed value or use the
equality operator (==) in place of the identity operator to ensure type invariant value
comparison.
Before:
After: