B. Fateh
B. Fateh

Reputation: 373

react hook form material ui checkbox array

i can't get values of checkbox array

const schema = yup.object().shape({
  modules: yup.array(),
});

component

{role === "user" &&
                divisions.map((division, i) => (
                  <Box key={division.name}>
                    <Typography variant='h6'>{division.name}</Typography>
                    {division.modules.map((m, j) => (
                      <Controller
                        key={m.name}
                        name={`modules[${i}][${j}]`}
                        control={control}
                        defaultValue={[division.name, m.name, false]}
                        render={({ field }) => (
                          <FormControlLabel
                            {...field}
                            label={m.name}
                            control={
                              <Checkbox
                                onChange={(e) => (e.target.value = "chen")}
                                color='primary'
                              />
                            }
                          />
                        )}
                      />
                    ))}
                  </Box>
                ))}

when i submit the form without checking anything i got a result like this

{//userinfo,  modules: [
//array per division and a nested array for modules access
 [ ["Admin-tools", "admin",false ],  ["Admin-tools", "Backup",false ] ] 
...other divisions and modules
 ]   }

this is the result i expect when i check fields and submit the form

 {//userinfo,  modules: [
    //array per division and a nested array for modules access
     [ ["Admin-tools", "admin",true],  ["Admin-tools", "Backup",true
 ] ] 
    ...other divisions and modules
     ]   }

but i got

{//userinfo,  modules: [
//array per division and a nested array for modules access
 [ [true],  [true] ] 
...other divisions and modules
 ]   }

Upvotes: 1

Views: 7198

Answers (2)

Moath
Moath

Reputation: 578

You need to pass checked and onChange to your checkbox and append/remove from the form array.

Steps:

  1. Create FromCheckboxes that'll serve as a container to a checkbox array
  2. Loop through your divisions and render a FromCheckbox for each division

Form.js

 <form onSubmit={handleSubmit(onSubmit)}>
      {divisions.map((division) => (
        <Box key={division.name}>
          <Typography variant="h6">{division.name}</Typography>
          <FormCheckboxes
            name="modules"
            control={control}
            parent={division.name}
            options={division.modules}
          />
        </Box>
      ))}
      <Button type="submit">Submit</Button>
    </form>

FormCheckboxes.js

import { useController } from "react-hook-form";
import { Checkbox, FormControlLabel } from "@material-ui/core";

const FormCheckBoxes = ({ options, ...rest }) => {
  const { field } = useController(rest);
  const { value, onChange } = field;

  return options.map((option) => {
    return (
      <FormControlLabel
        key={option.name}
        value={option.name}
        label={option.name}
        control={
          <Checkbox
            checked={value.some((formOption) => formOption[1] === option.name)}
            onChange={(e) => {
              const valueCopy = [...value];
              if (e.target.checked) {
                valueCopy.push([rest.parent, option.name, true]); // append to array
              } else {
                const idx = valueCopy.findIndex(
                  (formOption) => formOption[1] === option.name
                );
                valueCopy.splice(idx, 1); // remove from array
              }
              onChange(valueCopy); // update form field with new array
            }}
          />
        }
      />
    );
  });
};

export default FormCheckBoxes;

Updated Sandbox

Note that you'll still need to figure out how to tie them all in one form field. Now it won't work with multi-divisions.

Upvotes: 2

Karim Mokhtar
Karim Mokhtar

Reputation: 11

if you want the values of the checkbox in order to go to the form values and get it. you have to give each check box a name property. ex:

<FormControlLabel
   {...field}
   label={m.name}
   control={
    <Checkbox
     onChange={(e) => (e.target.value = "chen")}
     color='primary'
     name='name-one'
    />
   }
/>

Upvotes: 1

Related Questions