Skip to content

Forms

Forms allow users to enter and submit data, and provide them with feedback along the way. Cimpress UI includes many components that integrate with HTML forms.

How you submit form data depends on your framework, application, and server. By default, HTML forms are submitted by the browser using a full page refresh. You can take control of form submission by calling preventDefault during the onSubmit event, and make an API call to submit the data however you like.

By default, HTML forms are submitted by the browser using a full page refresh. You can specify where to submit form data using the action prop of the Form component. Each form field must have a name prop defined.

form-example.tsx
import { Button, Form, TextField } from '@cimpress-ui/react';
export function FormExample() {
return (
<Form action="https://example.com" method="post">
<TextField label="Name" name="name" />
<Button type="submit">Submit</Button>
</Form>
);
}

For uncontrolled forms, you can obtain form data during the onSubmit event. Each form field must have a name prop defined. All values will be serialized to strings.

form-example.tsx
import { Button, Form, TextField } from '@cimpress-ui/react';
export function FormExample() {
return (
<Form
onSubmit={(e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
// Do something with `formData`
fetch('https://example.com', {
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
body: formData,
});
}}
>
<TextField label="Name" name="name" />
<Button type="submit">Submit</Button>
</Form>
);
}

In controlled forms, you are in control of the values of each form field. You can still detect form submission by using the onSubmit event.

form-example.tsx
import { Button, Form, TextField } from '@cimpress-ui/react';
export function FormExample() {
const [name, setName] = useState('');
return (
<Form
onSubmit={(e) => {
e.preventDefault();
// Do something with `name`
alert(name);
}}
>
<TextField label="Name" name="name" />
<TextField label="Name" value={name} onChange={(value) => setName(value)} />
<Button type="submit">Submit</Button>
</Form>
);
}

Form validation is important to ensure user input is in an expected format and meets business requirements. Cimpress UI supports native HTML constraint validation, custom validation functions, real-time validation, and integration with server-side validation errors. All invalid fields will block forms from being submitted.

Native HTML constraints allow you to define constraints on each field such as required, minimum and maximum values, text formats such as email addresses, and even custom regular expression patterns. These constraints are checked by the browser when the user commits changes to the value (e.g., on blur) or submits the form.

Error messages are provided by the browser, and are localized using the browser/operating system language setting.

The example below shows a required input field that expects a postcode in a specific format:

See each component’s documentation for more details on the supported validation props.

As shown above, default error messages are provided by the browser, and are localized in the user’s preferred language. You can customize these messages by providing a function to the error prop. This function receives a list of error strings along with a ValidityState object describing why the field is invalid.

The example below modifies the previous example with custom error messages:

You can define your own validation rules by providing a function to the validate prop. This function receives the current field value, and can return a string or array of strings representing one or more error messages. These are displayed to the user after the value is committed (e.g., on blur).

The example below defines a custom validation error if you input the example postcode in the input field:

By default, validation errors are displayed to the user after the value is committed (e.g., on blur), or when the form is submitted. This avoids confusing the user with irrelevant errors while they are still entering a value.

In some cases, validating in real time can be desirable, such as when meeting password requirements. This can be accomplished by making the field value controlled, and setting the isInvalid and error props accordingly.

Type in the input field below to see validation errors change in real time:

Client-side validation is useful to give the user immediate feedback, but it’s only one half of the validation story. Data should also be validated on the backend for security and reliability, and your business logic may include rules which cannot be validated on the frontend.

Cimpress UI supports displaying server validation errors by passing the validationErrors prop to the Form component. This should be set to an object that maps each field’s name prop to a string or array of strings representing one or more errors. These are displayed to the user as soon as the validationErrors prop is set, and cleared after the user modifies each field’s value.

Submitting the following example form will simulate a server call that returns validation errors:

The validationErrors prop can also be used to integrate with server-side schema validation libraries like Zod, as well as server actions that are slowly becoming available in frameworks like Next.js and Remix.

By default, after a user submits a form with validation errors, the first invalid field will be focused. If you want to move focus elsewhere, you can prevent the default behavior by calling preventDefault during the onInvalid event.