-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
toNumber is lenient #2598
Comments
I would say this is expected. It is consistent with Vue 2. Changing it would create trouble for users when migrating. You can also use custom v-model modifiers to create a behavior that better fits your specific needs. |
Migration might be a concern, yes. Although I don't see how this could be a "feature". It's strange that typing I am working around this by not using the modifier, as you suggest. If you need this repeatedly it's annoying. Could you please tell me more about custom |
I'd say this being javascript it's consistent with javascript behaviour and I agree with @posva that one should just handle the value as string manually instead 🤔 |
@vhoyer saying it's consistent with JS is implying you know the underlying implementation. |
well, your right about that, but looking at the parsing behavior from |
I agree with you, it's strange that Fun fact: EDIT: although I guess the main reason why |
I assume you're referring to filters. Anything you used to do with filters you should now be able to do with methods instead. See: https://v3.vuejs.org/guide/migration/filters.html#migration-strategy
I believe the relevant docs are here: https://v3.vuejs.org/guide/component-custom-events.html#handling-v-model-modifiers |
@skirtles-code Thanks for the pointers, much appreciated!
Yes, I'm referring to filters. Sorry for the confusion, they are called pipes in Angular; Value Converters in Aurelia. Functions are a good enough replacement for (one-way) bindings and they'll be even more so when JS gets the pipe operator They are not usable in (two-way) v-model, though and that's really where their power was lost.
Thank you, I thought custom modifiers weren't a thing! It's no silver bullet, though. It only works on components and is defined per-component. Another limitation is that they don't take arguments, they're just booleans. This is also pretty limiting compared to filters, that may for example accept a date format, a default value, a rounding factor. It's amusing that the recommended way to manipulate a value updated by a On the other hand, you have to use a cumbersome syntax (that won't play nice with A basic example that has been mentioned before is wanting to convert empty strings to null in your model. Why would It looks like the focus of that issue has shifted from a |
In fact, Vue 2 supports filters only inside mustache expressions ( The last Vue version that supports filters inside I particularly like to use computed properties factories for reusing these logics, although typing them may be tricky in some cases. In Option API: function trim (key) {
return {
get () {
const val = this[key]
return typeof val === 'string' ? val.trim() : ''
},
set (val) {
this[key] = val.trim()
}
}
} In Composition API: function useTrim (originalRef) {
return computed({
get: () => {
const val = originalRef.value
return typeof val === 'string' ? val.trim() : ''
},
set: (val) => {
originalRef.value = val.trim()
}
})
} |
I wasn't aware Vue 2 only had one-way filters. Yeah, it's just functions then. ref factories is ok-ish. Although if you start stacking them it's crazy to have 3 computeds nested on top of a ref for something like Also declaring them as global template resources make them super-easy to use in any place (such as the previous example), whereas you'd need to import them in JS. |
This behavior causes bug. But compatibility is important. So I suggest adding this feature request as a option. |
@jods4 That's not really the reason I am aware of. What little value the one-way filters that we had them in Vue 2 added did not justify the compiler-problems that this custom non-JS compatible Syntax added, when compared to simple functions that can do the same in a way that any JS parser is fine with. |
@LinusBorg 100% agree with that. |
close vuejs#4946 close vuejs#2598 close vuejs#2604 This commit also refactors internal usage of previous loose implementation of `toNumber` to the stricter version where applicable. Use of `looseToNumber` is preserved for `v-model.number` modifier to ensure backwards compatibility and consistency with Vue 2 behavior.
close vuejs#4946 close vuejs#2598 close vuejs#2604 This commit also refactors internal usage of previous loose implementation of `toNumber` to the stricter version where applicable. Use of `looseToNumber` is preserved for `v-model.number` modifier to ensure backwards compatibility and consistency with Vue 2 behavior.
Version
3.0.2
Steps to reproduce
toNumber
(defined in@vue/shared
) usesparseFloat
, which is very lenient and will succeed if the first non-whitespace character is a digit (or sign).So
toNumber("1234abc")
will succeed and return 1234.toNumber
is used by the.number
modifier, so this surfaces in very observable ways to the end-user.A simple alternative would be
Number("1234abc")
, which does fail if the complete string isn't a valid number. LikeparseFloat
it does accept spaces at the beginning and end of string.What is expected?
If I input "12abc", given the behavior of
v-model.number
, I expectx
to be the string12abc
, which can then be handled as a validation error in user code.What is actually happening?
12 is assigned to
x
.EDIT Another defect caused by this implementation is that a textbox is not stable and its content changes unexpectedly for the end user.
If you have a textbox
<input v-model.number=x>
and typeabc123
, then the text stays the same when the component is updated. But if you type123abc
then the content is truncated to123
when the component updates.The text was updated successfully, but these errors were encountered: