Skip to main content

Form Building


Tip

We would appreciate any feedback on our tutorial guide. If you are stuck at any time, please reach out on our GitHub Discussions boardopens in a new window.


Before starting, complete Workplace Setup and follow one setup path from Getting Started.

Step 1: Create a Form Page​

In Visual Studio Code, open my-new-app project. From here, navigate into products/web/src/routes, and create a new folder, name "FormPage." Within this new folder, we'll be creating two new files, named "index.ts" and "FormPage.tsx".

Connect your page to the router in products/web/src/routes/Routes.tsx by including a new Route shown below:

<Router.Route path="/form-page" element={<FormPage />} />

You may reference the Page Routing tutorial for more information on creating pages.

Step 2: Building A Form​

Within FormPage.tsx we'll be adding the FormProvider and TextInput components to create a sample form. At the top of your file, copy, and paste the following import statements:

import React from 'react';
import { useForm } from '@uhg-abyss/web/hooks/useForm';
import { FormProvider } from '@uhg-abyss/web/ui/FormProvider';
import { Stack } from '@uhg-abyss/web/ui/Stack';
import { TextInput } from '@uhg-abyss/web/ui/TextInput';

A form can consist of many types of input components. In this form, we are using TextInput to populate the user's first name, middle name, and last name. Make sure all inputs are children of the FormProvider component. We are also using the Stack component to lay out the inputs with space between them.

Also be sure to provide default values for each field to the defaultValues prop within useForm. This ensures the form will properly reset to these default values whenever calling the reset method.

We can also include a SelectInput component as another alternative to collecting user input. Import the SelectInput component and then add the following code after the last TextInput component:

<SelectInput
label="Favorite Fruit"
validators={{ required: true }}
isClearable
isSearchable
model="favoriteFruit"
options={[
{ value: 'honeycrisp-apple', label: 'Honeycrisp Apple' },
{ value: 'pineapple', label: 'Pineapple' },
{ value: 'mango', label: 'Mango' },
{ value: 'banana', label: 'Banana' },
{ value: 'raspberry', label: 'Raspberry' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'blueberry', label: 'Blueberry' },
]}
/>

Lastly, we will create buttons in order to submit and clear the form inputs. The Group component is used to space the buttons. Import the Button and Group components, and then after the last SelectInput that you added above, within the body of FormProvider, insert the following code:

<Group justify="flex-end">
<Button variant="outline" onClick={handleClear}>
Clear Form
</Button>
<Button type="submit">Submit Form</Button>
</Group>

Let's add handlers for our submit and clear functions. Below the useForm() hook, add the two functions below for handleSubmit and handleClear.

const emptyDefaultValues = {
firstName: '',
lastName: '',
middleName: '',
favoriteFruit: '',
};
const form = useForm({
defaultValues: emptyDefaultValues,
});
const handleSubmit = (data) => {
console.log('Form Data', data);
alert('Submitted!');
};
const handleClear = () => {
form.reset();
};

Finally, attach the handleSubmit function by adding an onSubmit prop to your FormProvider.

<FormProvider state={form} onSubmit={handleSubmit}>

Step 3: Testing your Form​

At the end of creating a form & submitting the data, your code in FormPage.tsx should look like this:

import React from 'react';
import { useForm } from '@uhg-abyss/web/hooks/useForm';
import { Button } from '@uhg-abyss/web/ui/Button';
import { FormProvider } from '@uhg-abyss/web/ui/FormProvider';
import { Group } from '@uhg-abyss/web/ui/Group';
import { SelectInput } from '@uhg-abyss/web/ui/SelectInput';
import { Stack } from '@uhg-abyss/web/ui/Stack';
import { TextInput } from '@uhg-abyss/web/ui/TextInput';
const FormPage = () => {
const emptyDefaultValues = {
firstName: '',
lastName: '',
middleName: '',
favoriteFruit: '',
};
const form = useForm({
defaultValues: emptyDefaultValues,
});
const handleSubmit = (data) => {
console.log('Form Data', data);
alert('Submitted!');
};
const handleClear = () => {
form.reset();
};
return (
<FormProvider state={form} onSubmit={handleSubmit}>
<Stack>
<TextInput
label="First Name"
model="firstName"
isClearable
validators={{ required: true }}
/>
<TextInput label="Middle Name" model="middleName" isClearable />
<TextInput
label="Last Name"
model="lastName"
isClearable
validators={{ required: true }}
/>
<SelectInput
label="Favorite Fruit"
validators={{ required: true }}
isClearable
isSearchable
model="favoriteFruit"
options={[
{ value: 'honeycrisp-apple', label: 'Honeycrisp Apple' },
{ value: 'pineapple', label: 'Pineapple' },
{ value: 'mango', label: 'Mango' },
{ value: 'banana', label: 'Banana' },
{ value: 'raspberry', label: 'Raspberry' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'blueberry', label: 'Blueberry' },
]}
/>
<Group justify="flex-end">
<Button variant="outline" onClick={handleClear}>
Clear Form
</Button>
<Button type="submit">Submit Form</Button>
</Group>
</Stack>
</FormProvider>
);
};
export default () => {
return <FormPage />;
};

Great job, you have successfully built a form!

Table of Contents