How to use
Tutorial
Follow this tutorial to learn everything you need to know.
Overview
Creating a multi-step form like this in which there are questions dependent on previous answers can be a tedious and cumbersome task. Additionally, the challenges intensify when considering the need to store, share, or save such forms in a file or a database.
This is where Formity comes in, a solution designed to simplify the process. With Formity, building advanced multi-step forms is as straightforward as using a JSON. Say goodbye to complexities and experience form development like never before.
Dependencies
Formity depends on two packages, Mongu and React Hook Form. We suggest you to be at least a little familiar with these packages before moving on with this tutorial.
Example
To learn about Formity we highly suggest you to clone the following github repository.
git clone https://github.com/martiserra99/formity-example
This repository is set up with the Formity package. As we explain its usage, we'll be using the code within this repository as our point of reference.
cd formity-example
npm install
npm run dev
Installation
To install this package you have to run the following command.
npm install formity react-hook-form mongu
Components
To use this package the first thing you have to do is define the components that your form will use. You can find these at the components folder of the repository. They are created using Radix Themes, but you can create them in any way you want.
React Hook Form
There is one requirement when creating these components, though. If you take a look at the form fields like the TextField component, you will see that they need to be registered to the form, as this package depends on React Hook Form.
export default function TextField({ label, name, placeholder }) {
const { register, formState } = useFormContext()
const error = formState.errors[name]
return (
<Text as="label" className={styles.label}>
<Label as="div" mb="1" error={error}>
{label}
</Label>
<RadixTextField.Input
autoComplete="off"
placeholder={placeholder}
{...register(name)}
{...(error && { color: 'red' })}
/>
{error && <ErrorMessage mt="1">{error.message}</ErrorMessage>}
</Text>
)
}
FormityProvider
After defininig these components you have to provide them using the FormityProvider
component. You can find how this component is used in the main.jsx file.
import { FormityProvider } from 'formity'
// ...
const components = {
LayoutForm,
TextField,
TextArea,
Select,
RadioGroup,
CheckboxGroup,
Slider,
Range,
Button,
Back,
}
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<Theme appearance="dark" panelBackground="translucent">
<FormityProvider components={components}>
<App />
</FormityProvider>
</Theme>
</React.StrictMode>,
)
Formity
Once you have the components defined you can start to build the form. If you take a look at App.jsx, you will see that the form is created using the Formity
component.
import { Formity } from 'formity'
// ...
import form from './form'
export default function App() {
const [result, setResult] = useState(null)
function handleSubmit(result) {
setResult(result)
}
// ...
return (
<Center>
<Card>
<Formity form={form} onSubmit={handleSubmit} />
</Card>
</Center>
)
}
This component receives two props, the first one is the JSON form and the second one is the callback that will be called when the form is submitted.
JSON
The JSON that defines the form is in form.json. As you inspect it, you'll notice that this JSON is defined as an array of elements of different types. All these elements used in combination let you create any form you want in a very simple way.
The type of elements that exist are Form, Return, Variables, Condition and Loop. These elements let you create all kinds of logic and you can find more about them in the next part of the documentation.
Back
Finally, to navigate back to previous steps while using the form, you can use the useFormityForm()
hook. You can check out how it is used in the Back component.
import { useFormityForm } from 'formity'
import { Button } from '@radix-ui/themes'
export default function Back({ children }) {
const { onBack } = useFormityForm()
return (
<Button type="button" variant="outline" onClick={onBack}>
{children}
</Button>
)
}