Form data
A form has three "versions" of the data and two sets of errors. Here is what lives where and how it changes while the form is filled in. Every value below is real tinyval-vue output.
ts
const Signup = object({
name: pipe(string(), trim(), minLength(2)),
email: pipe(string(), email()),
age: optional(pipe(coerce.number(), min(18))),
});
const form = useForm(Signup, { initial: { name: '', email: '', age: '' } });values, data and changes
| Field | What's inside | Example | Used for |
|---|---|---|---|
form.values | What the user typed, as is | { name: ' Ivan ', email: 'ivan@mail.ru', age: '30' } | v-model |
form.data | Validated data after the schema: trim, coerce, no unknown keys. undefined while there are errors | { name: 'Ivan', email: 'ivan@mail.ru', age: 30 } | Preview, calculations |
data in handleSubmit | The same as form.data, at submit time | { name: 'Ivan', email: 'ivan@mail.ru', age: 30 } | Sending to the server |
form.changes | Only the changed fields, as typed (from values) | { email: 'petr@mail.ru' } | PATCH — see Editing |
The type of values comes from initial (strings in inputs), the type of data from the schema (age: number).
errors and allErrors
| Field | What's inside |
|---|---|
form.allErrors | All current schema and server errors — right away, even before the user typed anything |
form.errors | Only those that should be shown: for fields the user has left, all of them after submit. Plus server errors |
The format is the same as errors in tinyval: dot path → text of the first error. More about paths and texts in Validation result.
How the state changes
A user fills in a sign-up form:
| Step | errors | allErrors | valid | dirty | submitted | submitCount | submitSucceeded | data |
|---|---|---|---|---|---|---|---|---|
| 1. Form opened | {} | name, email: Required | false | false | false | 0 | false | undefined |
2. Typed ' I' into name | {} | name: Must be at least 2 characters long, email: Required | false | true | false | 0 | false | undefined |
| 3. Left the name field | name: Must be at least 2 characters long | as in step 2 | false | true | false | 0 | false | undefined |
| 4. Clicked "Submit" | name, email — all errors visible | as in step 2 | false | true | true | 1 | false | undefined |
| 5. Fixed it, the server answered 422 | email: The email has already been taken. | same | false | true | true | 2 | false | { name: 'Ivan', … } |
| 6. Changed the email, submitted | {} | {} | true | false | true | 3 | true | { name: 'Ivan', email: 'petr@mail.ru', age: 30 } |
What the table shows:
- Errors are computed right away (
allErrorsin step 1) but shown when the user leaves a field or clicks "Submit". - A server error goes into
errorsand makesvalidfalse, butdatastays — the data did pass the schema. The error disappears when the user changes that field. - After a successful submit
dirtyisfalseagain andchangesis empty: the current values count as saved.
What handleSubmit receives
Only if the form is valid, and only the validated data — after trim and coerce:
ts
// form.values: { name: ' Ivan ', email: 'petr@mail.ru', age: '30' }
const submit = form.handleSubmit((data) => {
data; // { name: 'Ivan', email: 'petr@mail.ru', age: 30 }
});The errors passed to onInvalid are the visible errors (form.errors) at submit time, i.e. all of them.
Other fields
| Field | Value |
|---|---|
touched | Fields the user has left: { name: true }. Paths as in errors |
validating | true while an async check is running |
submitting | true while the handleSubmit handler is running |
id | Base for field ids |
Full list — useForm.
See also
- useForm
- Validation result — the error and data format in tinyval