Add fields to form
To add a field to your form, you use the Field
component. It is headless and makes its state accessible to its children via a render prop.
Field component
The Field
component has a mandatory property called name
which you use to specify which field it is. If you use TypeScript, you don't have to type the name yourself thanks to autocompletion.
Children prop
As a child, you pass a function to the Field
component that returns JSX. You can use the first parameter of the function to access the current state of the field and the second parameter you have to pass to an HTML <input />
, <textarea />
or <select />
element to connect it to your form.
import { useForm } from '@modular-forms/preact';
type LoginForm = {
email: string;
password: string;
};
export default function App() {
const [loginForm, { Form, Field }] = useForm<LoginForm>();
return (
<Form>
<Field name="email">
{(field, props) => <input {...props} type="email" />}
</Field>
<Field name="password">
{(field, props) => <input {...props} type="password" />}
</Field>
<button type="submit">Login</button>
</Form>
);
}
Please let us know via email or the issues on GitHub if something is unclear or you have ideas on how we can further improve the API and documentation.
Headless design
The Field
component does not render its own UI elements. It is headless and provides only the data layer of the field. This allows you to freely define your user interface. You can use HTML elements, custom components or an external UI library.
Data types
If you want your field to capture a data type other than string, a second property called type
is required. However, based on your type definition, we will recognize this, point it out in your code and help you fill in the value using autocompletion. This way we know your data type at runtime and can ensure that only valid values are captured.
<Field name="age" type="number">
{(field, props) => <input {...props} type="number" />}
</Field>
Type safety
The API design of the Field
component results in a fully type-safe form. For example, if you change the name of a field, TypeScript will immediately alert you. Also, you can't mistype when adding an error message, because it is taken from the provided state of the field. More about this on the next page.
Field state
In addition to the current value and the error message of a field, the Field
component also tracks whether a field has been touched, is dirty or active.
Touched and dirty
A field is touched whenever the blur
event has been triggered at least once or an input has been made and is dirty if the current value does not correspond to the initial value.
Active state
A field is active when it is part of the DOM. The active state is important because by default Modular Forms only takes active fields into account, e.g. when validating or returning the current form values. If you don't want this behavior, you can use the keepActive
property of the Field
component to prevent a field from becoming inactive or the shouldActive
property or option of the Form
component or the various methods to ignore the active state entirely.
Why is there an active state?
The active state allows that when fields are shown or hidden depending on the value of another field, that only the values of the shown fields are validated and returned. The payment form in our playground shows this behavior.