Controlling the Checkbox in Material UI with React Hook Form.

React
スポンサーリンク
language

There are more elements to consider than when controlling Text Field and Radio in Material UI with React Hook Form, as follows, and they are related to each other. As a result, it requires relatively more work.

  • Setting initial values
  • Change the value
  • Set up a checkbox group (multiple checkboxes with the same name)

In this article, I will show you how to control the Checkbox in Material UI with React Hook Form.
The requirements to control are as follows

  • Support for default values (default check)
  • Control checkbox value changes.
  • Set up a Checkbox group using Material UI (multiple Checkboxes with the same name)
スポンサーリンク

Sample Code

import React from "react";
import { useForm, Controller } from "react-hook-form";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
import { FormHelperText, FormControl } from "@material-ui/core";

const items = [
  {
    id: 0,
    name: "Object 0"
  },
  {
    id: 1,
    name: "Object 1"
  },
  {
    id: 2,
    name: "Object 2"
  },
  {
    id: 3,
    name: "Object 3"
  },
  {
    id: 4,
    name: "Object 4"
  }
];

export default function CheckboxesGroup() {
  const defaultIds = [1, 3];

  const { control, handleSubmit, getValues, errors } = useForm({
    defaultValues: { item_ids: defaultIds }
  });

  const handleCheck = checkedId => {
    const { item_ids: ids } = getValues();
    const newIds = ids?.includes(checkedId)
      ? ids?.filter(id => id !== checkedId)
      : [...(ids ?? []), checkedId];
    return newIds;
  };

  return (
    <form onSubmit={handleSubmit(data => console.log("data", data.item_ids))}>
      ...
      <FormControl error={!!errors.item_ids?.message}>
        <FormHelperText>{errors.item_ids?.message}</FormHelperText>
        <Controller
          name="item_ids"
          render={props =>
            items.map((item, index) => (
              <FormControlLabel
                control={
                  <Checkbox
                    onChange={() => props.onChange(handleCheck(item.id))}
                    defaultChecked={defaultIds.includes(item.id)}
                  />
                }
                key={item.id}
                label={item.name}
              />
            ))
          }
          control={control}
        />
      </FormControl>
      ...
    </form>
  );
}
Material demo - CodeSandbox

Description of the control that meets the requirements

The requirements for controlling the Checkbox in Material UI with React Hook Form were as follows.

  • Corresponding to initial value
  • Control checkbox value changes.
  • Set up a Checkbox group using Material UI (multiple Checkboxes with the same name)

Here is an explanation of the code that satisfies this requirement.

Corresponding to initial value

To set initial values for a form controlled by React Hook Form, you need to set defaultValues in useForm().

 const { control, handleSubmit, getValues, errors } = useForm({
    defaultValues: { item_ids: defaultIds }
  });

You can set an input’s default value with defaultValue/defaultChecked(read more from the React doc for Default Values), pass defaultValues as an optional argument to useForm() to populate the default values for the entire form, or set values on an individualController component via its defaultValue property.

https://react-hook-form.com/v6/api

The initial values can be received by using getValues() in the function, or by using values in the Controller.

API ドキュメントPerformant, flexible and extensible forms with easy-to-use validation.react-hook-form.com

Control checkbox value changes.

If there is any change in the check box, the handleCheck function will be executed.

Within the handleCheck function, we are doing the following.

  • If the changed item ID is already in the value, delete it.
  • If the changed item ID is not already in the value, add it to the value.
const handleCheck = checkedId => {
  const { item_ids: ids } = getValues();
  const newIds = ids?.includes(checkedId)
      ? ids?.filter(id => id !== checkedId)
      : [...(ids ?? []), checkedId];
  return newIds;
};

Set up a Checkbox group using Material UI

To place multiple Material UI Checkboxes, create multiple checkboxes in the render of the React Hook Form’s Controller.

Be careful not to generate multiple controllers for each React Hook Form.

<Controller
  name="item_ids"
  render={props =>
    items.map((item, index) => (
      <FormControlLabel
        control={
          <Checkbox
            onChange={() => props.onChange(handleCheck(item.id))}
            defaultChecked={defaultIds.includes(item.id)}
          />
        }
        key={item.id}
        label={item.name}
      />
    ))
  }
  control={control}
/>

Also, when there is a change in the value in the Material UI’s Checkbox, changing the defaultChecked value in the Material UI’s Checkbox will cause an error in the Checkbox.

So, the defaultIds are

  • Keep the variable for the default value of the checkbox const.
  • The default value of the checkbox and the changed value are held separately.

to make it impossible to change the value of defaultChecked so that no error will occur.

const defaultIds = [1, 3];

Reference

Material UI + multiple checkboxes + default selected · Issue #1517 · react-hook-form/react-hook-form
I am trying to build a form which accommodates multiple 'grouped' checkboxes using Material UI. The checkboxes are created async from a HTTP Request. I ...

https://github.com/react-hook-form/react-hook-form/blob/master/app/src/controller.tsx

タイトルとURLをコピーしました