Forms
Creating rich forms is one of the key challenges in web development. Since there're plently of different ways and libraries to achieve the same thing, we provide a bunch of form components and utilities.
In this guide, you'll learn how to use our built-in form component and how different validation patterns are implemented.
Form Components
Flora ships several pre-built form components which implement the corporate design.
They accept props to control the functionality (more on that later) as well as accessibility attributes.
For more details on each component, also check the Components section.
TextInput
TextInput is the default input field. It is used for string-based values such as firstname or city, but can also be turned into an email, date or password field by passing in the correct
type prop.FileInput
FileInput is the equivalent to the HTML
<input type="file"> element.TextArea
TextArea is similar to TextInput, but is used specifically for multi-line string-based values such as a description or a biography.
SelectInput
SelectInput is the equivalent to the HTML
<select> element. It even takes plain <option> elements as children. It is used whenever only a limited set of values is eligible and the user has to choose a single one of them.Checkbox
Checkbox is the direct equivalent to the HTML
<input type="checkbox"> element. It should be used whenever the value is boolean, thus consists only of 2 values true and false. In general, checkboxes are used if the value represents a yes/no pair, for example "I accept the terms of service" or "Send me a newsletter". For values that represent a on/off pair or any other specific value pair that's not boolean, consider using the Toggle component.RadioGroup / Radio
RadioGroup is used to control a set of radio buttons. Radio itself is the equivalent to the HTML
<input type="radio"> element. They should be used whenever only a limited set of values is eligible and the user has to choose a single one of them.In comparison to the SelectInput, radio buttons should only be used if the number of available options is small or else it will get confusing. A good rule of thumb is a maximum of 5 radio buttons per radio group.
Radio should never be used by itself and only if there're at least 2 options available. Otherwise you most likely want to use a Checkbox instead.
Slider
Slider is another variation which different UX tradeoffs. It is useful if only a certain range of values is accepted and the steps are linear. Instead of having to type a value, the customer will get immediate feedback on dragging.
CheckboxCard
CheckboxCard is another variation of the Checkbox with additional properties for options that are better described with multiple data points.
RadioCard
RadioCard is similar to CheckboxCard but for Radios respectively.
It is supposed to be used with RadioGroup as well.
Controlling Form Components
Next to the components, we ship two React hooks to control those components in a simple and declarative way.
Those hooks are inspired by the react-form-hook
We use the concept of touching fields. A field only shows its validation state and error message if it's touched. We can configure whether we want to touch a field on change, blur or submit. Additionally, we can touch fields manually.
Check the Utilities section for a full overview of all options and return values.
useField
This hook uses useState under-the-hood and controls the state changes and validation for each field. The internal representation of a field contains the following keys:
- value
- isTouched
- isDisabled
- isRequired
- isLoading
- errorMessage
It takes initial field values as well as a validation map.
It returns an object containing all internal field properties listed above, 3 functions to update the field and a
props object which we can spread onto any of the above built-in components.Note: In order to correctly function with boolean values, an initial value must be passed.
useForm
This hook takes a list of fields, where a field is the output of the useField hook.
It returns a
submit and reset function to handle form submits.It automatically touches all fields on submit.
Submitting Forms
Action buttons with a
type of submit will automatically submit the form if it is within the form DOM element.If it is located outside of the DOM element, one can pass a unique
id to the form element and reference the same one in a form prop passed to the button.This is useful e.g. when using Modal and passing the button as an action.
Validation
Form validation is an important part of user-friendly forms and can happen at different stages depending on the use case.
To simplify the use of different validation pattern, the
useField hook accepts a showValidationOn configuration option that aims to simplify that.Validation on Submit
The most common validation pattern is to validate all fields once the user tries to submit a form.
Since it is the most common pattern, is it automatically done if we're using the
useForm hook to submit our forms.Upon submitting, every field is touched and thus reveals the validation state and error message.
Validation on Blur
Note: At Carla, if not explicitly stated, we always want to implement Validation on Submit.
Another common pattern is to validate a field once the user "leaves" the input field. For most components, that's when we lose focus.
To minimize distraction, the validation is hidden again if the user "re-enters" the input field. To achieve that, we can set
showValidationOn to blur.Validation on Change
Note: At Carla, if not explicitly stated, we always want to implement Validation on Submit.
Additionally, due to the immediate feedback, this type of validation can be really distracting, discouraging and sometimes even confusing to the customer. It should only be used with caution.
The last common validation pattern is immediate feedback. As soon as the user changes the initial value, the validation state is revealed and possible error messages are shown. To achieve that, we can set
showValidationOn to change.Async Validation
Another common task is asynchronous validation.
For example, a user enters his favored username. We can't validate that right away, but need to ask our backend if the username is still available.
We do not provide any predefined option or utility since this is often use-case specific and quite complex to generalize. But, we can use the provided hooks and field functions to achieve that nevertheless.