Form Control

Form Control provides context such as `isInvalid`, `isDisabled`, and `isRequired` to form elements

    SourceTheme source@chakra-ui/form-control

Import#

Chakra UI exports 4 components for Form Control:

  • FormControl: The wrapper that provides context and functionality for all children.
  • FormLabel: The label of a form section. The usage is similar to html label.
  • FormHelperText: The message that tells users more details about the form section.
  • FormErrorMessage: The message that shows up when an error occurs.
import {
FormControl,
FormLabel,
FormErrorMessage,
FormHelperText,
} from '@chakra-ui/react'

Usage#

<FormControl>
<FormLabel htmlFor='email'>Email address</FormLabel>
<Input id='email' type='email' />
<FormHelperText>We'll never share your email.</FormHelperText>
</FormControl>

Sample usage for a radio or checkbox group#

<FormControl as='fieldset'>
<FormLabel as='legend'>Favorite Naruto Character</FormLabel>
<RadioGroup defaultValue='Itachi'>
<HStack spacing='24px'>
<Radio value='Sasuke'>Sasuke</Radio>
<Radio value='Nagato'>Nagato</Radio>
<Radio value='Itachi'>Itachi</Radio>
<Radio value='Sage of the six Paths'>Sage of the six Paths</Radio>
</HStack>
</RadioGroup>
<FormHelperText>Select only if you're a fan.</FormHelperText>
</FormControl>

Error message#

FormErrorMessage will only show up when the property isInvalid in FormControl is true.

function errorMessageExample() {
const [input, setInput] = useState('')
const handleInputChange = (e) => setInput(e.target.value)
const isError = input === ''
return (
<FormControl isInvalid={isError}>
<FormLabel htmlFor='email'>Email</FormLabel>
<Input
id='email'
type='email'
value={input}
onChange={handleInputChange}
/>
{!isError ? (
<FormHelperText>
Enter the email you'd like to receive the newsletter on.
</FormHelperText>
) : (
<FormErrorMessage>Email is required.</FormErrorMessage>
)}
</FormControl>
)
}

Making a field required#

By passing the isRequired props, the Input field has aria-required set to true, and the FormLabel will show a red asterisk. This red asterisk can be overwritten by passing requiredIndicator to the FormLabel. If you want to indicate that a field is optional you can add optionalIndicator to the FormLabel

<FormControl isRequired>
<FormLabel htmlFor='first-name'>First name</FormLabel>
<Input id='first-name' placeholder='First name' />
</FormControl>

Select Example#

<FormControl>
<FormLabel htmlFor='country'>Country</FormLabel>
<Select id='country' placeholder='Select country'>
<option>United Arab Emirates</option>
<option>Nigeria</option>
</Select>
</FormControl>

Number Input Example#

<FormControl>
<FormLabel htmlFor='amount'>Amount</FormLabel>
<NumberInput max={50} min={10}>
<NumberInputField id='amount' />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</FormControl>

Usage with Form Libraries#

Form Libraries like Formik make it soooo easy to manage form state and validation. I 💖 Formik

function FormikExample() {
function validateName(value) {
let error
if (!value) {
error = 'Name is required'
} else if (value.toLowerCase() !== 'naruto') {
error = "Jeez! You're not a fan 😱"
}
return error
}
return (
<Formik
initialValues={{ name: 'Sasuke' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
actions.setSubmitting(false)
}, 1000)
}}
>
{(props) => (
<Form>
<Field name='name' validate={validateName}>
{({ field, form }) => (
<FormControl isInvalid={form.errors.name && form.touched.name}>
<FormLabel htmlFor='name'>First name</FormLabel>
<Input {...field} id='name' placeholder='name' />
<FormErrorMessage>{form.errors.name}</FormErrorMessage>
</FormControl>
)}
</Field>
<Button
mt={4}
colorScheme='teal'
isLoading={props.isSubmitting}
type='submit'
>
Submit
</Button>
</Form>
)}
</Formik>
)
}

Improvements from v1#

  • We've improved the accessibility of the FormControl component. Here are the changes:

    • id passed to the form control will be passed to the form input directly.
    • FormLabel will have htmlFor that points to the id of the form input.
    • FormErrorMessage adds aria-describedby and aria-invalid pointing to the form input.
    • FormHelperText adds/extends aria-describedby pointing to the form input.
    • isDisabled, isRequired, isReadOnly props passed to FormControl will cascade across all related components.
  • FormLabel is now aware of the disabled, focused and error state of the form input. This helps you style the label accordingly using the _disabled, _focus, and _invalid style props.

  • If you render FormErrorMessage and isInvalid is false or undefined, FormErrorMessage won't be visible. The only way to make it visible is by passing isInvalid and setting it to true.

Edit this page on GitHub

Proudly made inNigeria by Segun Adebayo

Deployed by Vercel