In Controlling Material UI’s Checkbox with React Hook Form, I introduced how to control Material UI’s Checkbox with React Hook Form v6.
After that, React Hook Form v7 was released.
The way to control Material-UI has changed a little in React Hook Form v7, so I will show you how to control Checkbox in Material UI v4 with typescript.
The control specification of the Checkbox introduced here is the same as the previous one, as follows.
And the completed checkbox form is the following form.
Sample Code
import React, { useState } from "react";
import { useForm, FieldValues, Controller } from "react-hook-form";
import Button from "@material-ui/core/Button";
import Checkbox from "@material-ui/core/Checkbox";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormGroup from "@material-ui/core/FormGroup";
import FormHelperText from "@material-ui/core/FormHelperText";
import FormControl from "@material-ui/core/FormControl";
import FormLabel from "@material-ui/core/FormLabel";
export default function App() {
const [submitData, setSubmitData] = useState<string>("");
const defaultCheckedValues = ["B"];
// Options
const options = [
{
title: "A"
},
{
title: "B"
},
{
title: "C"
},
{
title: "D"
}
];
const {
formState: { errors },
control,
setValue,
getValues,
handleSubmit
} = useForm<FieldValues>({
criteriaMode: "all",
defaultValues: { checkbox: defaultCheckedValues.join(",") }
});
const handleFormOnSubmit = (data: any) => {
setSubmitData(data.checkbox);
};
const handleCheck = (
option: { title: string },
event: React.ChangeEvent<{}>
) => {
let values: string[] = getValues("checkbox")?.split(",") || [];
values = values.filter((v) => v); // empty element deletion
let newValues: string[] = [];
if ((event.target as HTMLInputElement).checked) {
newValues = [...(values ?? []), option.title];
} else {
newValues = values?.filter((value) => value !== option.title);
}
setValue("checkbox", newValues.join(","));
return newValues.join(",");
};
return (
<>
<form
method="POST"
onSubmit={handleSubmit(handleFormOnSubmit)}
encType="multipart/form-data"
>
<FormControl
required
error={errors?.hasOwnProperty("checkbox")}
component="fieldset"
fullWidth
>
<FormLabel component="legend">Question.</FormLabel>
<FormHelperText>
{errors?.checkbox && errors?.checkbox.message}
</FormHelperText>
<FormGroup>
<Controller
name="checkbox"
control={control}
rules={{ required: "Please make a selection." }}
defaultValue=""
render={({ field, fieldState }) => (
<>
{options.map((option, i) => (
<FormControlLabel
{...field}
key={i}
label={option.title}
onChange={(event) =>
field.onChange(handleCheck(option, event))
}
control={
<Checkbox
defaultChecked={defaultCheckedValues.includes(option.title)}
/>
}
/>
))}
</>
)}
/>
</FormGroup>
</FormControl>
<Button type="submit" variant="contained" color="primary">
Submit
</Button>
</form>
<br />
Submitted content.
<br />
{submitData}
</>
);
}
Description of the control that meets the requirements
The requirements to be controlled were as follows.
The following is an explanation of the code that corresponds to each requirement.
Corresponding to initial value
You can do this without using the React Hook Form where it corresponds to the default value.
Put the items to be checked by default in the Material-UI Checkbox in an array.
const defaultCheckedValues= ["B",];
The defaultValues in the following code defines the initial values for the React Hook Form.
defaultChecked.join(“,”) makes the array comma-separated characters.
const {
formState: { errors },
control,
setValue,
getValues,
handleSubmit
} = useForm<FieldValues>({
criteriaMode: "all",
defaultValues: { checkbox: defaultCheckedValues.join(",") }
});
Next, define the default values for the Material-UI.
In the Checkbox defaultChecked, check if the defaultCheckedValues are filled with a value.
If the defaultCheckedValues are filled, defaultChecked will be true.
<Checkbox defaultChecked={defaultCheckedValues.includes(option.title)} />
You can now put a default check on it.
Control checkbox value changes.
When there is a change in the check box, the handleCheck function will be executed.
In the Within the handleCheck function, the following is done.
const handleCheck = (
option: { title: string },
event: React.ChangeEvent<{}>
) => {
// Get the checked values.
let values: string[] = getValues("checkbox")?.split(",") || [];
// empty element deletion
values = values.filter((v) => v);
// Reflect changes
let newValues: string[] = [];
if ((event.target as HTMLInputElement).checked) {
// Add a value
newValues = [...(values ?? []), option.title];
} else {
// Exclude values
newValues = values?.filter((value) => value !== option.title);
}
setValue("checkbox", newValues.join(","));
return newValues.join(",");
};
In the part to get the checked values, getValues() is used to get the checked values.
If there are no checked values, the values will be an empty array.
In the empty element removal part, the values retrieved by getValues() in React Hook Form v7 may contain empty values, so we exclude them.
https://react-hook-form.com/api/useform/getvalues/
Set up a Checkbox group in Material UI
To set up multiple Material UI Checkboxes, create a checkbox group in the render of the Controller of React Hook Form v7.
Be careful not to create multiple checkboxes for each React Hook Form v7 Controller.
<FormGroup>
<Controller
name="checkbox"
control={control}
rules={{ required: "Please make a selection." }}
defaultValue=""
render={({ field, fieldState }) => (
<>
{options.map((option, i) => (
<FormControlLabel
{...field}
key={i}
label={option.title}
onChange={(event) =>
field.onChange(handleCheck(option, event))
}
control={
<Checkbox
defaultChecked={defaultCheckedValues.includes(option.title)}
/>
}
/>
))}
</>
)}
/>
</FormGroup>
To get the value of the Checkbox in Material-UI controlled by React Hook Form v7 and manipulate the value, you need to write onChange in the FormControlLabel.
コメント