My App

Usage

How to use useMuiForm with different Material-UI components

Using with MUI Components

useMuiForm's register function automatically provides the correct controlled props for MUI components. Here's how to use it with common MUI inputs.

TextField

The most common use case - works with all TextField variants using controlled value/onChange:

import { useMuiForm } from 'usemuiform'
import { TextField } from '@mui/material'

const { register } = useMuiForm<{ email: string }>({
  defaultValues: { email: '' }
})

<TextField
  label="Email"
  type="email"
  {...register('email', {
    required: 'Email is required',
    pattern: {
      value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
      message: 'Invalid email address'
    }
  })}
/>

Select (with TextField)

Use TextField with select prop:

import { TextField, MenuItem } from '@mui/material'

<TextField
  select
  label="Role"
  {...register('role')}
>
  <MenuItem value="admin">Admin</MenuItem>
  <MenuItem value="user">User</MenuItem>
  <MenuItem value="guest">Guest</MenuItem>
</TextField>

Select (standalone)

Or use the standalone Select component:

import { Select, MenuItem } from '@mui/material'

<Select
  {...register('role')}
>
  <MenuItem value="admin">Admin</MenuItem>
  <MenuItem value="user">User</MenuItem>
  <MenuItem value="guest">Guest</MenuItem>
</Select>

Multiple Select

For multi-select, the value will be an array:

type FormState = {
  roles: string[]
}

<Select
  multiple
  {...register('roles')}
>
  <MenuItem value="admin">Admin</MenuItem>
  <MenuItem value="user">User</MenuItem>
  <MenuItem value="guest">Guest</MenuItem>
</Select>

Checkbox

Checkboxes are also controlled; register returns a checked prop along with helperText and error:

import { FormControlLabel, Checkbox, FormHelperText, FormGroup } from '@mui/material'

<FormGroup>
  {(() => {
    const { helperText, error, ...checkboxProps } = register('isActive')
    return (
      <>
        <FormControlLabel
          label="Is Active"
          control={<Checkbox {...checkboxProps} />}
        />
        <FormHelperText error={error}>{helperText}</FormHelperText>
      </>
    )
  })()}
</FormGroup>

Or simpler without helper text:

<FormControlLabel
  label="Accept Terms"
  control={<Checkbox {...register('acceptTerms')} />}
/>

Switch

Same pattern as Checkbox (controlled checked state):

import { FormControlLabel, Switch } from '@mui/material'

<FormControlLabel
  label="Enable Notifications"
  control={<Switch {...register('notifications')} />}
/>

DatePicker (MUI X)

Works with MUI X date pickers. register wires the picker up as a controlled component (the picker typically calls onChange(value) rather than passing a DOM event):

import { DatePicker } from '@mui/x-date-pickers'
import { LocalizationProvider } from '@mui/x-date-pickers'
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
import dayjs from 'dayjs'

type FormState = {
  birthDate: dayjs.Dayjs
}

const { register } = useMuiForm<FormState>({
  defaultValues: { birthDate: dayjs() }
})

<LocalizationProvider dateAdapter={AdapterDayjs}>
  <DatePicker
    label="Birth Date"
    {...register('birthDate', {
      validate: (value) => {
        if (value.isBefore(dayjs().year(2000))) {
          return 'Date must be after 2000'
        }
        return true
      }
    })}
  />
</LocalizationProvider>

DateTimePicker

Same as DatePicker:

import { DateTimeField } from '@mui/x-date-pickers'

<DateTimeField
  label="Appointment"
  {...register('appointmentTime')}
/>

Nested Fields

Use dot notation for nested objects:

type FormState = {
  person: {
    name: string
    email: string
  }
}

<TextField
  label="Name"
  {...register('person.name', { required: 'Name is required' })}
/>

<TextField
  label="Email"
  {...register('person.email', { required: 'Email is required' })}
/>

On this page