Reputation: 167
I'm going to make checkbox and select fields with Material UI. However, I don't how to handle on change event. The dropdown isn't selected if I selected one item of list, and clicking the checkbox isn't checked.
Here is the code:
import React from "react";
import { useForm, useFieldArray } from "react-hook-form";
import {
FormControlLabel,
FormLabel,
FormGroup,
FormControl,
Button,
Box,
MenuItem,
Select,
Checkbox
} from "@material-ui/core";
import "./styles.css";
export default function App() {
const { register, setValue, control } = useForm({
defaultValues: {
infoGp: [
{
title: "",
restricted: false,
prohibited: false,
bus: false,
close: false
}
]
},
mode: "onBlur"
});
const { fields, append, remove } = useFieldArray({
control,
name: "infoGp"
});
const handleAddItem = () => {
append({
title: "",
restricted: false,
prohibited: false,
bus: false,
close: false
});
};
return (
<div className="App">
{fields.map((item, index) => {
return (
<Box border={1} p={3}>
<Box mb={4}>
<FormControl>
<Select
name={`infoGp${index}.title`}
value={`${item.title}`}
// onChange={titleChange}
displayEmpty
ref={register}
>
<MenuItem value="">Title</MenuItem>
<MenuItem value="mr">Mr.</MenuItem>
<MenuItem value="mrs">Mrs.</MenuItem>
<MenuItem value="miss">Miss</MenuItem>
</Select>
</FormControl>
</Box>
<Box>
<FormControl component="fieldset">
<FormLabel component="legend">Type of Location</FormLabel>
<FormGroup className="permitType">
<FormControlLabel
control={
<Checkbox
checked={item.restricted}
inputRef={register}
// onChange={permitTypeChange}
name={`infoGp${index}.restricted`}
/>
}
label="restricted"
/>
<FormControlLabel
control={
<Checkbox
checked={item.prohibited}
inputRef={register}
// onChange={permitTypeChange}
name={`infoGp${index}.prohibited`}
/>
}
label="prohibited"
/>
<FormControlLabel
control={
<Checkbox
checked={item.bus}
inputRef={register}
// onChange={permitTypeChange}
name={`infoGp${index}.bus`}
/>
}
label="bus stop"
/>
<FormControlLabel
control={
<Checkbox
checked={item.close}
inputRef={register}
// onChange={permitTypeChange}
name={`infoGp${index}.close`}
/>
}
label="close zone"
/>
</FormGroup>
</FormControl>
</Box>
{index > 0 && (
<Button
variant="contained"
color="secondary"
onClick={() => remove(index)}
>
remove
</Button>
)}
</Box>
);
})}
<Box mt={5}>
<Button variant="contained" color="primary" onClick={handleAddItem}>
add item
</Button>
</Box>
</div>
);
}
Should I use setValues or setState to handle onChange?
codesandbox here: https://codesandbox.io/s/react-hook-form-field-array-on-checkbox-select-g6gq9?file=/src/App.js:0-3872
Upvotes: 2
Views: 2447
Reputation: 2666
I have a FormCheckbox component with the MUI Checkbox in there.
That FormCheckbox is part of a UI Library in which we handle as much as possible.
The FormCheckbox component in the Pages Components should be as simple as possible and looks like this:
const onChangeSubscription = (e: ChangeEvent<HTMLInputElement>) => {
console.log(`CheckBox Changed !!: Target Value = ${e.target.checked}`);
};
....
<FormCheckbox
name={'subscription'}
label={'Yes, I want a subscription'}
onChange={onChangeSubscription}
/>
The FormCheckbox component looks like this:
Making use of:
import { ChangeEvent } from 'react';
import { useFormContext, Controller } from 'react-hook-form';
import { Checkbox as MuiCheckbox } from '@mui/material';
import Box from '@mui/material/Box';
import FormControlLabel from '@mui/material/FormControlLabel';
import styled from '@emotion/styled';
interface PropsInterface {
name: string;
value?: boolean;
label: string;
onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
}
const Checkbox = styled(MuiCheckbox)`
padding-right: 10px;
`;
export const FormCheckbox = (props: PropsInterface) => {
const { control, watch, setValue, getValues } = useFormContext();
const { name, value, label, onChange } = props;
const realValue = value ? value : false;
const onChangeHandler = (e: ChangeEvent<HTMLInputElement>) => {
setValue(name, !getValues()[name], {
shouldDirty: true,
shouldTouch: true,
shouldValidate: true,
});
if (typeof onChange === 'function') {
onChange(e);
}
};
return (
<Box>
<Controller
name={name}
control={control}
defaultValue={realValue}
render={() => (
<FormControlLabel
control={
<Checkbox onChange={onChangeHandler} checked={watch(name)} />
}
label={label}
/>
)}
/>
</Box>
);
};
Upvotes: -1
Reputation: 1094
You can use Controller
and control
for the checkbox in react-hook-form
version 7.
Here is an example: https://codesandbox.io/s/rhf-controller-material-ui-9ik00?file=/src/App.js
Upvotes: 1