Installation# With Yarn
Copy yarn add @formiz/core @formiz/validations
Or with NPM
Copy npm install @formiz/core @formiz/validations
Concept# The idea behind Formiz is to allow you to build advanced forms with
multiple steps, complex validations and a good UX without pain.
The main idea is to build fields as independent reusable components.
Fields can be anything , not just inputs. Once you have built your fields,
you can use them everywhere.
When you use a field built with Formiz, you can apply validations rules on it.
Only the mounted fields will apply their validation to the current step and to the form.
Copy
< MyField
name = " email "
type = " email "
required = " Email is required "
validations = { [
{
rule : isEmail ( ) ,
message : 'Not a valid email' ,
}
] }
/>
Formiz core does not provide any styles, so you can use it with any UI library and style you want .
Use it with Chakra UI , ReactStrap , Material UI or your own styles.
Usage# Create your first custom field# A custom field can be anything, not just inputs.
Here there is an example with an input, but you can litteraly turn anything into a field and you will get validation for free !
1. Create a new field# Create a MyField.js
file, then import the useField
hook from @formiz/core
Copy import React from 'react'
import { useField } from '@formiz/core'
export const MyField = ( ) => {
}
2. Pass props to the hook# Get the props from the MyField component and pass it to the hook.
Copy import React from 'react'
import { useField } from '@formiz/core'
export const MyField = ( props ) => {
const { } = useField ( props )
}
3. Make it works# Create the <input>
and make it interactive like this:
Copy import React from 'react'
import { useField } from '@formiz/core'
export const MyField = ( props ) => {
const { setValue , value } = useField ( props )
return (
< input
value = { value ?? ย '' }
onChange = { e => setValue ( e . target . value ) }
/ >
)
}
3. Display error# Display the errorMessage
below the <input>
.
Copy import React from 'react'
import { useField } from '@formiz/core'
export const MyField = ( props ) => {
const { errorMessage , isValid , setValue , value } = useField ( props )
return (
< div >
< input
value = { value ?? ย '' }
onChange = { e => setValue ( e . target . value ) }
/>
{
! isValid
&& errorMessage
}
</ div >
)
}
4. Improve UX and accessibility# Add a custom label and add *
if the field is required. Allow to change the input type. Add css classes for style. Display error only if the field is blured or the form/step is submitted. Don't apply the is-error
class if the input is focused. Add id
, for
and aria attributes for accessibility. Copy import React from 'react'
import { useField } from '@formiz/core'
export const MyField = ( props ) => {
const {
errorMessage ,
id ,
isValid ,
isSubmitted ,
setValue ,
value ,
} = useField ( props )
const { label , type , required } = props
const [ isTouched , setIsTouched ] = React . useState ( false )
const showError = ! isValid && ( isTouched || isSubmitted )
return (
< div className = { ` demo-form-group ${ ( showError ) ? 'is-error' : '' } ` } >
< label
className = " demo-label "
htmlFor = { id }
>
{ label }
{ ! ! required && ' *' }
</ label >
< input
id = { id }
type = { type || 'text' }
value = { value ?? ย '' }
className = " demo-input "
onChange = { e => setValue ( e . target . value ) }
onBlur = { ( ) => setIsTouched ( true ) }
aria-invalid = { showError }
aria-required = { ! ! required }
aria-describedby = { showError ? ` ${ id } -error ` : null }
/>
{ showError && (
< div id = { ` ${ id } -error ` } className = " demo-form-feedback " >
{ errorMessage }
</ div >
) }
</ div >
)
}
Use your field in a form# 1. Create the form# Copy import React from 'react'
import { Formiz } from '@formiz/core'
export const MyForm = ( ) => {
return (
< Formiz >
{ }
</ Formiz >
)
}
2. Connect the form with the useForm
hook# Copy import React from 'react'
import { Formiz , useForm } from '@formiz/core'
export const MyForm = ( ) => {
const myForm = useForm ( )
return (
< Formiz
connect = { myForm }
>
{ }
</ Formiz >
)
}
3. Handle submit# Copy import React from 'react'
import { Formiz , useForm } from '@formiz/core'
export const MyForm = ( ) => {
const myForm = useForm ( )
const handleSubmit = ( values ) => {
console . log ( values )
}
return (
< Formiz
connect = { myForm }
onValidSubmit = { handleSubmit }
>
< form
noValidate
onSubmit = { myForm . submit }
>
{ }
< button
type = "submit"
disabled = { ! myForm . isValid }
>
Submit
</ button >
</ form >
</ Formiz >
)
}
4. Add fields to the form# Each field need a property "name" which will be the key in the object of values.
So, be sure this key is unique by form .
Copy import React from 'react'
import { Formiz , useForm } from '@formiz/core'
import { isEmail } from '@formiz/validations'
import { MyField } from './MyField'
export const MyForm = ( ) => {
const myForm = useForm ( )
const handleSubmit = ( values ) => {
console . log ( values )
}
return (
< Formiz
connect = { myForm }
onValidSubmit = { handleSubmit }
>
< form
noValidate
onSubmit = { myForm . submit }
>
< MyField
name = " firstName "
label = " First Name "
required = " First Name is required "
/>
< MyField
name = " lastName "
label = " Last Name "
required = " Last Name is required "
/>
< MyField
name = " email "
label = " Email "
validations = { [
{
rule : isEmail ( ) ,
message : 'This is not a valid email' ,
} ,
] }
/>
< button
type = " submit "
disabled = { ! myForm . isValid }
>
Submit
</ button >
</ form >
</ Formiz >
)
}
๐ง Multi Steps form# Oh wait... you want to turn the form into a multi steps form?
Good news, that pretty easy!
You already have your fields so we just need to update the form to use steps.
Each FormizStep need a property "name" , be sure this key is unique by form.
Copy import React from 'react'
import {
Formiz ,
FormizStep ,
useForm ,
} from '@formiz/core'
import { isEmail } from '@formiz/validations'
import { MyField } from './MyField'
export const MyForm = ( ) => {
const myForm = useForm ( )
const handleSubmit = ( values ) => {
console . log ( values )
}
return (
< Formiz
connect = { myForm }
onValidSubmit = { handleSubmit }
>
< form
noValidate
onSubmit = { myForm . submitStep }
>
< FormizStep
name = "step1"
>
< MyField
name = " firstName "
label = " First Name "
required = " First Name is required "
/>
< MyField
name = " lastName "
label = " Last Name "
required = " Last Name is required "
/>
</ FormizStep >
< FormizStep
name = "step2"
>
< MyField
name = " email "
label = " Email "
validations = { [
{
rule : isEmail ( ) ,
message : 'This is not a valid email' ,
} ,
] }
/>
</ FormizStep >
{ }
{ ! myForm . isFirstStep && (
< button type = " button " onClick = { myForm . prevStep } >
Back
</ button >
) }
{ myForm . isLastStep ? (
< button type = " submit " disabled = { ! myForm . isValid } >
Submit
</ button >
) : (
< button type = " submit " disabled = { ! myForm . isStepValid } >
Continue
</ button >
) }
</ form >
</ Formiz >
)
}
That's it ๐#