From 0865c40063a6bc1c61c2889bdc61c0a1974110b1 Mon Sep 17 00:00:00 2001 From: Stas Lashmanov Date: Wed, 8 Jul 2020 04:25:05 +0300 Subject: [PATCH 1/7] Initial --- .../0000-fully-controlled-form-elements.md | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 active-rfcs/0000-fully-controlled-form-elements.md diff --git a/active-rfcs/0000-fully-controlled-form-elements.md b/active-rfcs/0000-fully-controlled-form-elements.md new file mode 100644 index 00000000..91472ae7 --- /dev/null +++ b/active-rfcs/0000-fully-controlled-form-elements.md @@ -0,0 +1,213 @@ +- Start Date: (fill me in with today's date, YYYY-MM-DD) +- Target Major Version: 3.x +- Reference Issues: +- Implementation PR: + +# Summary + +Change `v-model` behaviour to be in full control over form elements' value. + +# Basic example + +Consider such a component: + +```html + + + +``` + +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. + +# Motivation + +The main goal of any state-centric UI library or framework is solving the problem of UI and state synchronization. This is commonly achieved through bindings for various UI parts. + +Bindings could be expressed in form of one of the following: + +- **One-way binding** – UI reacts to bound state value. + + A Vue version of this is called `v-bind`. User input is handled by event listeners. + +- **Two-way binding** – UI reacts to bound state value, but state value reacts to input from UI as well. + + In Vue this is called `v-model`. User input is handled by the model. + +But here is the problem: what should happen when input from UI is transformed by the model or an event listener? + +Moreover, what should happen when there's no event listener at all in a one-way binding case? Should any input be prevented then? + +There are two ways to deal with this kind of problem: *Controlled* and *Uncontrolled* bindings. + +In Controlled approach UI always corresponds to state whenever a state to UI binding is present. +In Uncontrolled approach UI is non-blocking and user input can break out of state synchronization. + +A common example is an `` that has state value bound to its DOM value. +An Uncontrolled version of the `` would allow for any user input no matter what the actual state value is. +A Controlled version would not allow user input that doesn't correspond to final state value. + +## Current state + +Vue implements uncontrolled approach for form elements bindings (i.e. elements that can accept user input). + +### Comparison with other frameworks + +| Binding\Library | Vue | React | Svelte | Angular 2+ | +|-----------------|--------------|----------------|--------------|--------------| +| Two-way binding | Uncontrolled | Not applicable | Controlled | Uncontrolled | +| One-way binding | Uncontrolled | Controlled | Uncontrolled | Uncontrolled | + +Vue follows Angular approach to controlled bindings, while Svelte provides a nice balance between strictly controlled and uncontrolled behaviour. + +[Compare Vue and Svelte behaviour](!!!!!!!) + +Examples of two-way binding: + +```html + +``` +```html + + +``` +```html + + +``` + +Example of one-way binding: + +```html + +``` + +This is considered a one-way binding as well: + +```html + +``` + +## Problems of uncontrolled approach + +(watchers, forceUpdate, input prevention) + +## Benefits of suggested mixed approach + +Fully controlled bindings have their downsides as well: + +- Clumsy uncontrolled element design (via refs in React for example). We'd like to preserve declarative style as much as possible and avoid manual state synchronization. +- Very hard to work with uncontrolled forms (i.e. when only initial value is set and no further state synchronization is needed). + + ```html + + + ``` + + In React you'd have to create an uncontrolled input for every case like that or sync that value via event listener. Since Vue is often used to enhance an existing application this is crucial for some users. + +This main focus of this RFC is to find a fair balance between controlled and uncontrolled approach, similar to what Svelte has right now. Shortly, `v-model` behaviour should change to controlled behaviour, `v-bind` should work as is. + +There are many benefits that controlled `v-model` has over uncontrolled. + +### Improved Developer Experience + +Controlled `v-model` gives you full control over value transformations. No more need for manual state synchronization, input prevention and any other hacks that were necessary before. + +```js +{ + model: { + get() { return this.value }, + set(value) { + // it just works, user is unable to enter 'foo' + if (value === 'foo') return; + this.value = value; + }, + } +} +``` + +### Higher-order models + + + +### Uncontrolled bindings still possible + +It would still be possible to have uncontrolled bindings when necessary. You can achieve that by switching to one-way bindings instead. + +```html + +``` + +# Detailed design + +Below is a comprehensive list of all elements affected: + +* `` except for `` which does not support `v-model` +* `