Form validation is an effective way to control the type of values that are provided in the proper format, preventing security vulnerabilities, malicious users, and entering incorrect data. It guarantees the data submitted matches the requirement. There are many validation frameworks/libraries that are used to handle React form validation in web applications; Informed is one such tool.
What is Informed?
Informed is a React form validation tool used to create robust forms. It’s a simple framework that enables you to add custom inputs, dynamic forms, and multi-step forms to your application while making it simple to specify input error messages. It resolves the hassle of handling form state.
Getting Started With Informed
This section will walk you through integrating the Informed React validation library into your application, along with validating fields and creating custom inputs. In addition, we'll create a React application and install the Informed library by performing either of the following commands:
or
After installing the library, we’ll modify our App.css
file by pasting the code block below:
* {
overflow-x: hidden;
}
.App {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
color: #000;
min-height: 100vh;
width: 100vw;
padding: 20px;
}
form {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
width: 700px;
padding: 15px;
box-shadow: 10px 10px 15px lightblue;
border: 1px solid #eee;
border-radius: 2px;
}
div {
display: flex;
flex-direction: column;
width: 100%;
padding: 5px;
}
input {
width: -webkit-fill-available;
padding: 5px 10px;
margin: 5px 0;
}
button {
border: none;
margin-top: 10px;
padding: 10px 25px;
border-radius: 5px;
color: #fff;
background-color: #000;
cursor: pointer;
}
span {
color: #ff0000;
}
React Form Validation with Informed
In this section, we’ll go over how to include Informed in your application. By default, the Informed library features native DOM input elements that are controlled by the React form library. This makes it easy to retrieve and manipulate form values; it handles everything related to the form state. Using the code block below, we’ll alter the App.js
component:
import { Form, Input, Debug } from 'informed';
import './App.css';
const App = () => (
<div className="App">
<Form>
<div>
<Input className="input" name="name" label="Name" placeholder="Elon" />
<Input
className="input"
name="age"
type="number"
label="Age"
/>
<Input
className="input"
name="phone"
label="Phone"
formatter="+234 (###)-###-####"
/>
<button type="submit">Submit</button>
</div>
<Debug/>
</Form>
</div>
);
export default App;
The code block above demonstrates how components imported from the Informed library are simply implemented. It’s critical to note the Debug component; this component displays the whole state of your form in real time, allowing for easier debugging. Also, the formatter prop shows you how to format input values. This can be added to text inputs as well.
Validation Hooks
The Informed library has a variety of hooks that help with various parts of managing simple to complex React forms in your application. We'll be looking at it in this section:
useFormState
The useFormState
hook from the Informed library gives you access to the form state properties:
import { Form, Input, useFormState } from 'informed';
const ComponentUsingFormState = () => {
const formState = useFormState();
return (
<pre>
<code>{JSON.stringify(formState.values, null, 2)}</code>
</pre>
);
};
const App = () => (
<div className="App">
<Form>
<div>
<Input name="name" label="Name:" />
<Input name="occupation" label="Occupation:" />
<button type="submit">Submit</button>
</div>
<div>
<h5>Component using formState:</h5>
<ComponentUsingFormState />
</div>
</Form>
</div>
);
In the code block above, in ComponentUsingFormState
, you can access the form values by using the dot notation formState.values
:
useFormApi
The useFormApi
hook from the Informed library allows you to gain access to the form API functions. You can alter the value of an input using the functions that formApi
provides for React form validation:
...
import { Form, Input, useFormApi } from "informed";
const RandomSetterButton = () => {
const formApi = useFormApi();
return (
<button
type="button"
onClick={() =>
formApi.setValue(
"name",
Math.floor(Math.random() * Math.floor(Number.MAX_SAFE_INTEGER))
)
}
>
Random
</button>
);
};
const SetValuesButton = () => {
const formApi = useFormApi();
return (
<button
type="button"
onClick={() => formApi.setValues({ name: 'Asta', age: 26, color: "Green" })}
>
All
</button>
);
};
const SetTheseValuesButton = () => {
const formApi = useFormApi();
return (
<button
type="button"
onClick={() => formApi.setTheseValues({ age: 27, color: "Yellow" })}
>
Age & Color
</button>
);
};
const App = () => (
<Form onSubmit={({ values }) => window.alert(JSON.stringify(values, null, 2))}>
<div>
<Input name="name" label="First Name:" />
<Input name="age" label="First Name:" type="number" />
<Input name="color" label="Favorite Color:" />
<RandomSetterButton />
<SetValuesButton />
<SetTheseValuesButton />
<button type="submit">Submit</button>
</div>
</Form>
);
...
As shown in the code block above, the RandomSetterButton
component uses setValue
to target a single input. In this case, the name input is targeted, and the value is set to a random number. The SetTheseValuesButton
component uses the setTheseValues
function to change the values of name, age, and color inputs. Also, the SetValuesButton
component uses setValues
to set the input values of both age and color to different values. One of the important useFormApi
functions is the onSubmit
function. This gives you access to the form values, which can be used as payload to an endpoint.
useFieldApi
The useFieldApi
hook gives you access to the field API functions using a dot notation:
...
import { Form, Input, useFieldApi } from "informed";
const ComponentUsingFieldApi = () => {
const fieldApi = useFieldApi("name");
return (
<button
type="button"
onClick={() =>
fieldApi.setValue(
' Math.floor(Math.random() * Math.floor(Number.MAX_SAFE_INTEGER))'
)
}
>
Random
</button>
);
};
const App = () => (
<Form>
<div>
<Input name="name" label="Name:" initialValue="Joe" />
<button type="submit">Submit</button>
<h5>Component using fieldApi:</h5>
<ComponentUsingFieldApi/>
</div>
</Form>
);
...
The name
field having the initialValue
Meliodas, changes to a random number when the random button is clicked:
useFieldState
The useFieldState
hook gives you access to the field state attributes:
...
import { Form, Input, useFieldState } from 'informed';
const ComponentUsingFieldState = ({ name }) => {
const fieldState = useFieldState(name);
return (
<>
<h5>Component using fieldState: {name}</h5>
Render: {Math.random()}
<pre>
<code>{JSON.stringify(fieldState, null, 2)}</code>
</pre>
</>
);
};
const App = () => (
<Form>
<div>
<Input name="name" label="Name:" />
<Input field="age" label="Age:" type="number" />
<button type="submit">Submit</button>
</div>
<div>
<ComponentUsingFieldState name="name" />
<ComponentUsingFieldState name="age" />
</div>
</Form>
);
...
From the code block above, the name
field is passed into the useFieldState
hook as an argument, and can be used to keep track of every name attribute in the form state:
Form Validation Methods
Simple Validation
Informed forms provide the validate prop to handle field-level validation. You can pass in rules from a function to validate an input field, or mark it as required
:
...
import { Form, Text } from 'informed';
const validate = (value) => {
if (!value || value.length < 5)
return (
<span>Field must be at least five characters</span>
)
};
const App = () => {
return (
<Form
onSubmit={({ values }) => window.alert(JSON.stringify(values, null, 2))}>
<Input name="color" label="Color:" validate={validate} required />
<Input name="food" label="Food:" validate={validate} />
<button type="submit">Submit</button>
</Form>
);
};
...
Validation Control
For more control when validating, passing validateOn
props to fields makes Informed more flexible in handling React form validation. You can also choose to control when the error message shows using the showErrorIfError
, showErrorIfTouched
, and showErrorIfDirty
props:
...
const App = () => (
<div className="App">
<Form
onSubmit={({ values }) => window.alert(JSON.stringify(values, null, 2))}
>
<div>
<h4>validateOn="blur" ( default )</h4>
<Input
name="username1"
label="Username1"
required
validate={validate}
/>
<h4>validateOn="change"</h4>
<Input
name="username2"
label="Username2"
validateOn="change"
required
validate={validate}
/>
<h4>validateOn="change" && showErrorIfDirty</h4>
<Input
name="username3"
label="Username3"
validateOn="change"
showErrorIfDirty
required
validate={validate}
/>
<h4>validateOn="change-blur"</h4>
<Input
name="username4"
label="Username4"
validateOn="change-blur"
required
validate={validate}
/>
<h4>validateOn="change-submit"</h4>
<Input
name="username5"
label="Username5"
validateOn="change-submit"
required
validate={validate}
/>
<h4>validateOn="blur-submit"</h4>
<Input
name="username6"
label="Username6"
validateOn="blur-submit"
required
validate={validate}
/>
<h4>validateOn="submit"</h4>
<Input
name="username7"
label="Username7"
validateOn="submit"
required
validate={validate}
/>
<h4>validateOnMount</h4>
<Input
name="username8"
label="Username8"
validateOnMount
required
validate={validate}
/>
<h4>validateOnMount && showErrorIfError</h4>
<Input
name="username9"
label="Username9"
validateOnMount
showErrorIfError
required
validate={validate}
/>
<button type="submit">Submit</button>
</div>
<div>
<Debug values errors invalid validating />
<button type="submit">Submit</button>
</div>
</Form>
</div>
Validation Messages
This method aids you in displaying custom error messages for built-in validations. You can achieve this feat by making use of the errorMessage
prop:
...
import {
Form,
Input,
Debug
} from 'informed';
const validate = value => {
if (!value || value.length < 5)
return 'Field must be at least five characters';
};
const App = () => (
<Form
errorMessage={{ required: 'This field is required for your profile!' }}
onSubmit={({ values }) => window.alert(JSON.stringify(values, null, 2))}>
<Input
name="name"
label="First name:"
required
errorMessage="There is a problem with this field!"
/>
<Input
name="last"
label="Last name:"
required
errorMessage={{ required: 'Last name is required!' }}
/>
<Input name="favoriteColor" label="Favorite color:" required />
<button type="submit">Submit</button>
<Debug values errors invalid valid />
</Form>
);
...
Basic Form Validation
Informed allows you to create custom validation inputs that can be used across your application. Next, we’ll explore the useField
and useForm
hooks to create a custom form:
...
import { useForm, useField, Debug } from 'informed';
const CustomForm = ({ children, ...rest }) => {
const { formController, render, userProps } = useForm(rest);
return render(
<form
{...userProps}
onReset={formController.reset}
onSubmit={formController.submitForm}
onKeyDown={formController.keyDown}>
{children}
</form>
);
};
const CustomInput = props => {
const { render, informed, fieldState, userProps, ref } = useField({
type: 'text',
...props
});
const { id, label, ...rest } = userProps;
const { error, showError } = fieldState;
return render(
<>
<label htmlFor={id}>{label}</label>
<input
{...rest}
{...informed}
ref={ref}
style={showError ? { border: 'solid 1px red' } : null}
/>
{showError && <small style={{ color: 'red' }}>{error}</small>}
</>
);
};
const App = () => (
<div className="App">
<CustomForm
onSubmit={({ values }) => window.alert(JSON.stringify(values, null, 2))}
>
<div>
<CustomInput
field="name"
label="First name:"
validateOn="change"
required
minLength={5}
/>
<button type="submit">Submit</button>
</div>
<Debug values errors />
</CustomForm>
</div>
);
...
Using the useField
and useForm
hooks, a custom form and input component was generated in the code block above. When utilizing either hook, you must always call the render method obtained from both hooks:
Conclusion
In this article, we explored the Informed library for handling React form validation in applications. We also covered creating custom inputs and custom validation error messages. To see more of what the library offers, check out their docs and GitHub repository.