Closed rpkilby closed 8 years ago
@rpkilby Thanks for creating this issue, I was planning on tackling it to day, but work got in the way. :)
Curious - couldn't this just be done with custom two-way filters? Maybe I'm missing something.
@davidkhess Indeed, it seems possible: https://jsfiddle.net/posva/8whzuL16/1/
@davidkhess Yes, it's possible. This issue, however, is about adding built-in support.
The problem I've had with this approach is that it's unexpected, coming from other frameworks. All of them 'have the magic built in' to handle number inputs. Writing your own filter to handle this, while possible, is very sub-optimal. The compromise between what @yyx990803 envisions and what I'd like seems to be adding transforms for v-model
.
@Morgul completely understand – I tend to favor less magic.
@rpkilby @Morgul Do you have a real use-case about any modifier you think should exist?
There is already a number parameter for text inputs: http://vuejs.org/guide/forms.html#number Isn't it enough?
@posva Not really, no. As discussed in #1713, it's surprising when you're getting a number out of a number input. While vue has a way of handling that (the number
directive), we discussed the fact that it could be better implemented as a transform, because then vue's syntax for handling these sorts of issues is consistent. This is the exact type of thing transforms were made for; number should be one.
@posva - It seems like a date transform for the date/datetime input types would be useful. However, I'm more interested in being able to register transforms. eg,
@rpkilby I think two way filters work out pretty well for this. The guide actually talk about this http://vuejs.org/guide/custom-filter.html#Two-way-Filters
Maybe a more explicit example showing v-model="when | date"
in the docs help out. I don't think a modifier is needed because two way filters already address this issue
@posva - yes, and we currently do this. I guess my problem is that I have vague (and I want to emphasize, very minor) dissatisfactions with the API for dealing with various data types. I have some thoughts that haven't really formed into anything cohesive.
type="checkbox"
(and to be fair, this is kind of necessary).type="number"
, and require a number
paramater.The result of all of these leaves us with:
<input type="checkbox" v-model="foo" />
<input type="number" v-model="bar" number />
<input type="date" v-model="baz | date" />
number
parameter is an easy source of bugs.number
get special treatment anyway? Should it be replaced by a filter?Example:
<input type="text" v-model="title" />
<input type="text" v-model="slug | lower | kebab" lazy />
<input type="date" v-model.date="publishOn" />
<input type="number" v-model.number="priority" />
Edit:
@rpkilby very nice analysis and writeup. Agreed, things are inconsistent.
@rpkilby thanks for the thoughtful input - we'll definitely improve this in 1.1 :)
@yyx990803 any new thoughts on this given the deprecation of filters outside of interpolated text in Vue 2.x?
Ditto, removing filters seems to beg for some hook on v-model to accomplish type/value transformations.
The problem with other type transformations other than .number
is that the conversion from the value back to string is not straightforward. e.g. for a date transformer, if you programmatically set the bound value to a Date
object, there's no way for Vue to know how to display it as text in the input box. Then again we are back to similar concepts as two-way filters.
Type transformations also by definition makes the view out of sync with the underlying state.
My take on this use case is that instead of the implicit magic conversions, let v-model
just sync what the user actually inputs with an underlying value (the source of truth), and then build derived values separately based on that value.
For example, you can perform these transformations only when you need to send it to the server for persistence. Or, use computed properties based on the bound value if you need to display it elsewhere in a different format.
My take on this use case is that instead of the implicit magic conversions, let
v-model
just sync what the user actually inputs with an underlying value (the source of truth), and then build derived values separately based on that value.
Preface: upon rereading, it's unclear if you're talking about removing the number
directive or not, but my argument can be applied to any sort of transformation between a form's data and what's stored in a model, not just numeric inputs.
For simple use cases, this may be sufficient (and in some cases preferred). However, I have a use case with about 60 <input type="number">
fields. A rare case, admittedly, but it's what I've got. Since I need to perform math operations on the user input, I would end up with significantly more than 60 computed properties for those operations, and then the code to save to the server would be an annoying (but not complex) merger of the computed properties and the underlying data object.
I agree in principal with "let v-model
just sync what the user actually inputs", however my contention is that when a user is presented with a <input type="number">
field the user's intention is to input a number, so Vue should store it as a number. The user doesn't know that HTML5's spec for number inputs is weird; They were asked for a number, so they input a number.
I'm fine if I have to do some work somewhere (specifying a transform, a two way filter, or something like that), but I don't want to have to define 60+ computed properties and then write code to try and merge those computed properties with another object just so I can turn it into JSON to send to my server. It feels like an inelegant solution, compared to other frameworks.
My use case is numeric inputs, but being a little more pedantic, you could apply the same logic to the values for check boxes (true/false vs string values), date fields, radio buttons, etc. Any time you have a large number of properties that need special handling, you'll run into this problem. I just don't think that 'use a computed property' scales well.
I'd be a lot more sanguine if it felt like there was a clear path forward that had the same elegance I'm used to in the rest of the framework.
@Morgul .number
is still available because the conversion from a number to a string is very straightforward. That is not the case for other arbitrary types, e.g. Date.
For argument:
Date
objects.Date
objects.you can perform these transformations only when you need to send it to the server for persistence. Or, use computed properties based on the bound value if you need to display it elsewhere in a different format.
For a one-off type transformation this is fine, but as @Morgul said, this is problematic at scale. In our latest project we dealt with a lot of dates. In lieu of type transforms, we used two-way filters. At some point, we made the switch to using moment.js. Updating the filter was incredibly simple.
v-model="someDate | date"
)In contrast, using computed properties would have been more painful:
Date
s to moment
s would require globally updating each computed property. Probably not a huge issue in practice, but definitely more prone to error.Type transformations also by definition makes the view out of sync with the underlying state.
I would disagree - the view is a representation of the underlying state. The type transformation simply transforms an unrepresentable type (Date object) into something that is representable (date string).
if you programmatically set the bound value to a Date object, there's no way for Vue to know how to display it as text in the input box. Then again we are back to similar concepts as two-way filters.
Type transformations are definitely similar to two-way filters, however they seem like they would be much more simple. An intentionally minimal API makes sense.
Possible API:
Vue.typeTransform('date', {
render(value) {
return value ? value.isoformat() : '';
},
parse(value) {
return value ? new Date(value) : undefined;
},
});
This would be in line with the coerce functionality in component props.
@rpkilby Opened https://github.com/vuejs/vue/issues/3666
A boolean modifier would have been great.
This works perfect, indeed a boolean modifier would also be a nice addition 👍
Az
On Wed, 1 Aug 2018, 18:31 Jerry Jacobs, notifications@github.com wrote:
This works perfect, indeed a boolean modifier would also be a nice addition 👍
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/vuejs/vue/issues/2002#issuecomment-409656290, or mute the thread https://github.com/notifications/unsubscribe-auth/AOYJoQCojZNAjrbZxY_4QLHVHItaRZCqks5uMeYLgaJpZM4Gy4Xw .
From @Morgul's comment in #1713:
It would also seem useful to be able to register custom transformations. eg, datetime transformations for Moment.js objects.