Input States
Inputs have two implicit states which manages certain CSS classes.
Dirty Input
Inputs are deemed dirty when their current value differs from the previously saved. If configured, the dirtyCssClass
will be added to the input. The saved value can be updated using the save
method or a Submit
button.
Invalid Input
Inputs have the invalidCssClass
added to them when their validation fails.
Form States
Forms have access to three states for their inputs: dirty
, errors
, and values
. Forms also have a isDirty
and isValid
signal.
Dirty State
// Example state
F.dirty == {
password: {
old: '',
new: '********'
},
nickname: {
old: '',
new: 'root'
}
}
The dirty
state is linked to an internal commit state that contains the form's default values or whatever values last set by save
. Keys are only added to the dirty
state when input values differ from their committed state. The changes are provided as an object containing both the old and new value(e.g. { old: '', new: 'user@domain.tld' }
).
There are two ways of updating the commit state. The first and easiest being Submit
which will save the commit state when the form is valid. The other option is using the save
method and a button which will save the form regardless of its validity. If there's a need to check the current commit state, it can be done with a combination of dirty
and values
(see Internal Commit State).
Calling reset
or using the Reset
button will discard all changes. This includes inputs that are otherwise valid. Users wanting to save valid inputs and reset invalid ones can do so with dirty
, errors
, and save
(see Partial Form Saving).
Dirty Signal
(Since v1.3.0)
If any input is deemed dirty then the signal returns true
otherwise it returns false
.
<Show when={F.isDirty}>You have unsaved changes</Show>
Errors State
// Example state
F.errors == {
username: 'is not an email address',
password: 'is required'
}
Validation happens on...
- inputs using the
onBlur
andonChange
events, - forms using the
onSubmit
event and aSubmit
button, - and/or using the
validate
method.
Whenever an input fails validation, the errors
state will contain the name of invalid inputs as keys and the first error they encountered as values. Keys are added to the state when an input becomes invalid and they are removed when the input becomes valid.
Valid Signal
(Since v1.3.0)
If any input is deemed invalid then the signal returns false
otherwise it returns true
.
<Show when={!F.isValid}>Please correct the errors below</Show>
Values State
// Example state
F.values == {
username: 'user@domain.tld',
password: '********',
nickname: 'root'
}
The values of inputs is always available through the values
state. This state is primarily updated using the onKeyUp
event on inputs which simply copies event.target.value
. It's also updated using the onBlur
and onChange
events which transform values before setting them.
Internal Commit State
ValidatedForm instances don't have access to the internal commit state but, since the dirty state is based off of the commit state, the internal commit state can easily be derived with a bit of logic. Simple implementation of commit state logging.
const F = ValidatedForm({
username (value) {
if (value === '') return 'is required'
},
nickname () {
// Accept any value
}
})
// Outputs the commit state to console
const log = () => {
const state = {}
Object.keys(F.values).forEach((name) => {
// Note we're accessing the old value of dirty
state[name] = F.dirty[name] ? F.dirty[name].old : F.values[name]
})
console.log('current commit state:')
console.dir(state)
}
<F.Form>
<F.Text name='username' />
<F.Text name='nickname' />
<F.Submit />
<F.Reset />
<F.Button onClick={log} label='Log State' />
</F.Form>
Partial Form Saving
Simple implementation of partial form saving.
const F = ValidatedForm({
username (value) {
if (value === '') return 'is required'
},
nickname () {
// Accept any value
}
})
// Saves all the dirty inputs that are valid
const save = () => {
Object.keys(F.dirty).forEach((name) => {
// Saving one input at a time
if (!F.errors[name]) F.save(name)
})
}
<F.Form>
<F.Text name='username' />
<F.Text name='nickname' />
<F.Submit />
<F.Reset />
<F.Button onClick={save} label='Save' />
</F.Form>