Form control
A FormControl
is a value of the form. It has a visual representation in the view the user can control.
It can hold any type of value, but cannot have child components.
Creating a FormControl
is as simple as:
import { FormControl } from '@banquette/form';
const control = new FormControl(value, validator);
The value
There are two types of values in a FormControl
:
value
: this is the current value of the control, the one parents see and that will be used outside the form,defaultValue
: this is the original value of the control, the one that was set when the control has been constructed.
To update value
:
control.setValue('new value');
TIP
This will impact the control's states, like make it dirty, and maybe trigger a validation.
To update defaultValue:
control.setDefaultValue('a new default');
WARNING
This will do nothing else than storing your new default value. To set the default value as current value, you must reset the control.
To reset the control:
control.reset();
This will have the following effects:
- Set the value back to the default value,
- Unmark the following states:
changed
,touched
,dirty
,validated
, - Blur the control if focused,
- Clear validation errors.
Resetting the control does not impact the following states: disabled
, busy
, validating
, concrete
.
The view
A FormControl
in itself is, in essence, just a container for a value. It has no visual representation in the browser.
That's to maintain a separation of concerns and to keep it framework-agnostic.
So to get a full usable form component, you need to associate it with a view model.
The view model makes the bridge between the HTML of your page and the FormControl
.
Create your own view models can be a complex exercise, depending on the components you're trying to create. This is discussed in detail in the Your own views section.
But luckily, Banquette
comes natively with a Vue 3 implementation of the basic form components, that you can check out here.
The usage is a simple as:
<bt-form-text :control="yourControl"></bt-form-text>
to create a text input for example.
TIP
I advise you to keep reading the Form
documentation first to really understand how the system works
before digging into the specifics of the views.
For now, you can see the view as a way to update the value of the FormControl
, nothing else matters 🎵.
Virtual control
Now that we understand that a FormControl
and its views
are two different things, we can discuss the concept of virtual
controls.
A FormControl
is virtual when it has no view associated with it.
A virtual control is (by default) invisible to most operations of the form:
- it's ignored by the validation, so it will not produce any validation error,
- it's disabled,
- it's ignored by its parent component (when iterating over its children or updating its value).
To make the control concrete (inverse of virtual), you have to associate it with a view, like we've seen in the previous section.
If you use the @banquette/vue-ui package for the view components, it is as simple as doing:
<bt-form-text :control="yourControl"></bt-form-text>
The view will automatically bind with the control which will enable it and make it concrete.
TIP
If you really want to use a control without a view, you can force it to become concrete
by calling:
control.markAsConcrete();
You can also make a whole form concrete in one call by selecting all components and then calling markAsConcrete
on the collection:
// Get is a glob pattern that will select all child components recursively.
form.getByPattern('**').markAsConcrete();
But this is generally not advised, you should create a view for all your controls.
TIP
If you use @banquette/vue-ui, you can create an invisible form component:
<bt-form-hidden :control="yourControl"></bt-form-hidden>
If you don't use @banquette/vue-ui and want to create views by yourself (using Vue
or a different framework), please refer
to the dedicated documentation.
Focus / blur
The last functionality specific to FormControl
is the focus()
and blur()
methods that are quite self-explanatory.
You can call focus()
to give the focus to the control, and blur()
for the opposite.
But what makes it worth the talk is the way it works.
When you call focus()
, the control will not change the focused
state of the control.
Instead, it will only call the view to ask for focus.
The view is then responsible for calling back the control when the focus have been gained to update the focused
flag.
This ensures that the focused
flag is trustworthy, as it will only ever be true if the view has confirmed the focus.
NOTE
You can also note that calling focus()
on a FormControl
with no view will do nothing, as it should because having
the focus without a view makes no sense.