API to support: reward early, punish late UX
See original GitHub issueIs your feature request related to a problem? Please describe. The best UX when it comes to validation is a concept sometimes referred to as “reward early, punish late”.
In practice, it means that:
- if a value is invalid, as soon as the user fixes the input it should be green again (reward early).
- if a value is valid, it shouldn’t become red until the user finishes its input – typically at
blur
orchange
events (punish late).
A sample interaction, would be:
- Say field A must be at least 4 characters, and is currently “1235” (valid).
- User wants to fix this to 1234, so it removes the “5” -> the input should not flash red yet!
- User types the “4”
- Value is committed (e.g. blur event), 1234 is valid, field stays green.
On the other hand, if field was “123” and red, as soon as the user types “4” the error should go away.
I have built such UX on top of vuelidate, but it could easily have built-in support, with just two small additions that I’m proposing below.
Describe the solution you’d like
Today $error
indicates if the error should be displayed in UI, and is based on $invalid
+ $touch()
events (a non-dirty value is not displayed in red).
I propose to optionally change $error
behavior to match the UX described above.
This would be opted-in by users using with a new option { useCommit: true }
.
There would be a single new API $commit()
to support this feature.
How it would work:
- If option
{ useCommit: true }
is not used -> everything works as today.$commit()
is a synonym for$touch()
.
Otherwise:
- When touched, if
$invalid
is false then update$error = false
, like today. - When touched, if
$invalid
becomes true -> do nothing! - When
$commit()
is invoked, call$touch()
, then set$error = $invalid
.
Top level API $validate()
should call $commit()
on each field instead of $touch()
.
And that’s it.
Describe alternatives you’ve considered You can build this on top of the Vuelidate object, but it’s a bit hacky / more complicated.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:6
- Comments:6 (3 by maintainers)
Just so you know, in the end we replaced Vuelidate with our own validation code that includes this built-in.
To answer your questions:
$error
is meant to be what the UI binds to, the proposal here is to have an option to slightly change the timing of the feedback, in other words to change the behavior$error
.@input
, basically$touch
). It should be red only when the user is done (typically@change
). For example, if I’m typing a phone number, the box shouldn’t be red while I’m typing the digits because I’m not finished yet.I think of commit more as an action than a state. You can create a
$committed
flag and reset it anytime$touch
is called, but you can also do without it. Basically the 3 (actually 2) steps is listed above should work well enough:See it in action! Here there’s a validator on the time format. In particular, notice how when I’m going from
06:30
to06:25
there’s no flashes of red when the box contains06:
, an invalid input!Will do but it won’t be until Sunday or Monday.