-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix(input): fix step
validation for input[number]
/input[range]
#15264
Conversation
Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257
Step support works like min / max, but with the following caveat. Currently, only Firefox fully implements the spec. Other browsers (Chrome, Safari, Edge) have issues when the step value changes after the input has been changed. They do not adjust the input value to a valid value, but instead set the stepMismatch validity state. Angular will take this validity state, and forward it as the ngModel "step" error. Adjusting the error ourselves would add too much code, as the logic is quite involved.
0083fc1
to
bed92aa
Compare
bed92aa
to
10870c8
Compare
@@ -2748,7 +2749,8 @@ describe('input', function() { | |||
expect($rootScope.value).toBe(30); | |||
|
|||
// 0.3 - 0.2 === 0.09999999999999998 | |||
$rootScope.$apply('min = 0.2; step = 0.09999999999999998; value = 0.3'); | |||
$rootScope.$apply('min = 0.2; step = (0.3 - 0.2)'); | |||
helper.changeInputValueTo('0.3'); |
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.
Not changing the scope value (e.g. $rootScope.$apply('value = '0.3')
), because ngModel
does not overwrite programmatically changed scope values unless the validity of the input changes. Depending on the order in which the validators are run and the previous state, this may lead to the scope value remaining 0.3
instead of being set to undefined.
expect(inputElm).toBeValid(); | ||
expect($rootScope.value).toBe(20); | ||
expect($rootScope.form.alias.$error.step).toBeFalsy(); | ||
forEach({ |
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 they
?
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.
I want to repeat the describe
block. they
is for repeating it
blocks.
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.
Oh, I see. Problem is you won't be able to see if ngStep or step failed, because the its have the same name. Maybe put the attribute name in the its?
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.
It will be in describe
's...description, so it is visible.
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.
Oh, that's right!
expect($rootScope.value).toBe(10); | ||
expect(inputElm.val()).toBe('10'); | ||
expect($rootScope.form.alias.$error.step).toBeFalsy(); | ||
it('should correctly validate even in cases where `(x*y % x !== 0)`', function() { |
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.
Isn't this case an implementation detail? Can we give a better description?
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.
It short of is, but value % step === 0
is the obvious way to implement it and it is the exact implementation that leads into errors. I mean we wouldn't have this issues if we had implemented it differently, but we want to explicitly test that the obvious implementation falls short.
That said, I am always open to suggestions 😉
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.
Maybe "in cases where the JS floating point arithmetic fails"?
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.
Works for me.
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.
Changed.
// and `viewValue` is expected to be a valid stringified number. | ||
var value = Number(viewValue); | ||
|
||
// Due to limitations is Floating Point Arithmetic (e.g. `0.3 - 0.2 !== 0.1` or |
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.
is -> in/of
var value = Number(viewValue); | ||
|
||
// Due to limitations is Floating Point Arithmetic (e.g. `0.3 - 0.2 !== 0.1` or | ||
// `0.5 % 0.1 !== 0`), we need to make sure all numbers are integers before proceeding. |
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.
need to convert all numbers to integers?
@Narretz, PTAL. |
LGTM |
Related to 9a8b8aa and #15257. Fixes the issue discussed in 9a8b8aa#commitcomment-19108436. Fixes #15257 Closes #15264
Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257 Closes angular#15264
Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257 Closes angular#15264
This reverts commit 90c08b8 feat(input): re-add support for binding to `input[range]` This commit re-applies the related (previously reverted) commits. A follow-up commit will make the support opt-in in order to avoid a breaking change. Included commits: - 296da4b - `feat(input): add support for binding to input[type=range]` (previously reverted with 6a167e8) - b78539b - `fix(input[range]): correctly handle min/max; remove ngMin/ngMax support` (previously reverted with aa60491) - 90c08b8 - `feat(input[range]): support step` (previously reverted with 5b633d8) fix(input): fix `step` validation for `input[number][ng-range-input]` Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257 Closes angular#15264
Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257 Closes angular#15264
Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257 Closes angular#15264
Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257 Closes angular#15264
Related to 9a8b8aa and #15257. Fixes the issue discussed in 9a8b8aa#commitcomment-19108436. Fixes #15257 Closes #15264
Related to 9a8b8aa and #15257. Fixes the issue discussed in 9a8b8aa#commitcomment-19108436. Fixes #15257 Closes #15264
Related to 9a8b8aa and angular#15257. Fixes the issue discussed in angular@9a8b8aa#commitcomment-19108436. Fixes angular#15257 Closes angular#15264
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix.
What is the current behavior? (You can also link to an open issue here)
step
validation (forinput[number]
/input[range]
) fails on some occasions due to limitations of Floating Point Arithmetic (as described in #15257) and does not fully account for astepBase
as descussed in 9a8b8aa#commitcomment-19108436.What is the new behavior (if this is a feature change)?
It works as expected!
BTW, according to the spec, when there is no
min
attribute (to determine the step base), but there is a value attribute, then the step base is set to the value of that. In our case this doesn't apply very well, because the value attribute is not compatible withngModel
and is essentially ignored.Does this PR introduce a breaking change?
No
Please check if the PR fulfills these requirements
Docs have been added / updated (for bug fixes / features)Other information:
[ng-input-range]
.Fixes 9a8b8aa#commitcomment-19108436
Fixes #15257