vuejs / rfcs

RFCs for substantial changes / feature additions to Vue core
4.87k stars 546 forks source link

Fully controlled form elements #188

Open CyberAP opened 4 years ago

CyberAP commented 4 years ago

Change v-model behaviour to be in full control over the displayed value.

Rendered RFC

jods4 commented 4 years ago

I am a bit confused by this RFC.

The basic example says:

Currently Vue will render anything that user enters in the even though state value is different from what the user actually sees. After the change user only sees the first character, which perfectly corresponds to the actual state.

I find that untrue, in the following repro only the first char is displayed: https://codesandbox.io/s/v-model-decomposed-camel-case-84732

The RFC talks about $forceUpdate but never mentions the fact that whenever the v-model expression triggers (in the reactivity sense) the input will be updated.

In particular, this includes when v-model updates the source and this is why the sandbox above only displays a single character:

CyberAP commented 4 years ago

I find that untrue, in the following repro only the first char is displayed: https://codesandbox.io/s/v-model-decomposed-camel-case-84732

Thanks for pointing that out, this shows that current behaviour is inconsistent. For setup it works, for options it does not. But the behaviour should be the same both for setup and options.

jods4 commented 4 years ago

I see, I have never used the options API. I had the impression that in Vue 3 the Options API was re-implemented on top of reactivity, which intuitively would mean that they behave the same. If they don't I agree the behaviour should be consistent and predictable.

Maybe the RFC should be more clear about how v-model works differently in each API and how it's gonna unify them. Currently there's no mention of either. All examples are based on Options API.

From my first read I got the impression that it wants to change the way v-model works -- or add alternative ways/mode (e.g. .controlled). I don't quite understand how modifying v-model that already works for Composition will fix Options: shouldn't the underlying layer be unified first?

Not trying to challenge the RFC but as a Composition API user I don't quite get it.

CyberAP commented 4 years ago

Yes, this is worth mentioning in RFC, I'll update it later accordingly. I didn't mention it beforehand because I was unaware that setup does not have this problem.

ByScripts commented 4 years ago

I find that untrue, in the following repro only the first char is displayed: https://codesandbox.io/s/v-model-decomposed-camel-case-84732

Thanks for pointing that out, this shows that current behaviour is inconsistent. For setup it works, for options it does not. But the behaviour should be the same both for setup and options.

Is it expected than even for setup(), the behavior is different for get/set and computed ?

https://codesandbox.io/s/v-model-decomposed-camel-case-5ftt7

CyberAP commented 4 years ago

Is it expected than even for setup(), the behavior is different for get/set and computed ?

https://codesandbox.io/s/v-model-decomposed-camel-case-5ftt7

It is not, thanks for adding that! I'll update RFC later to reflect this inconsistency as well.

CyberAP commented 4 years ago

Added a few more examples:

Also expanded Composition API section with current inconsistencies.

jods4 commented 3 years ago

I don't think the "fix readonly on checkboxes" motivation is good.

Is the code example even working? It doesn't propagate the update event, sure, but the UI would be left in an inconsistent state. In this simple fiddle, the model doesn't change but you can see the checkbox state still changes when you click it: https://jsfiddle.net/tkz305s8/

In this case I think there are cleaner way to "fix HTML". If you're writing a v-checkbox component, you could fix the problem at the HTML level by cancelling the event:

<template>
  <input type=checkbox @click="e => { if (readonly) e.preventDefault() }">
</template>

What this does is clear and works at lowest level. (Fun fact: despite its name click event is called for every checkbox change, including if the change is trigger by keyboard).

(If you can, a better option is to use disabled but it has minor differences to readonly)

CarterLi commented 2 years ago

A form element should always be controlled because that's how binding works.

<input type="text" value="TEXT" />

A developer binds property value of element input to string TEXT. In this case, property value of element input should always be TEXT, which makes the input box behave like readonly.

<input type="text" :value.attr="'TEXT'" />

A developer binds attribute value of element input to string TEXT. In this case, attribute value of element input should always be TEXT. However, attribute value is the initial value of an input element. In this case, users can freely change text in the input box.

That's how binding works, and so called controlled. This behavior should be constant, and should not change depending on what elements it applies.

tve commented 1 year ago

I'm trying to understand the status of this RFC... In the top-level readme it states

Open a new thread in Discussions and make sure to set category to "RFC Discussions"

Is there such a discussion thread? Sorry for the dumb question...

leopiccionia commented 1 year ago

I'm trying to understand the status of this RFC...

This PR was created before the implementation of GitHub discussions. As far as I know, there's no related Discussion thread, but one could be opened.

mahnunchik commented 2 weeks ago

This would be a useful improvement