
I am working on a react project and have built a form framework which wraps material ui, around the redux form.
** sandbox https://codesandbox.io/s/condescending-banzai-re6l3
I am unsure how fix a bug - where if the grouped checkbox field is set as validate - to only have a required message appear under the group of checkboxes - then demand all checkboxes to be required.
Here is the current code base
//renderGroupedCheckboxes
import React from "react";
import { Field } from "redux-form";
import FormControl from "@material-ui/core/FormControl";
import FormLabel from "@material-ui/core/FormLabel";
import FormGroup from "@material-ui/core/FormGroup";
//import FormHelperText from '@material-ui/core/FormHelperText';
import renderCheckboxField from "./renderCheckboxField";
const renderGroupedCheckboxes = (fields) => (
  <FormControl component="fieldset" fullWidth={true}>
    <FormLabel component="legend">{fields.label}</FormLabel>
    <FormGroup row>
      {fields.names.map((item, j) => {
        return (
          <Field
            key={j}
            name={item}
            component={renderCheckboxField}
            label={fields.options[j].label}
            onChange={function (e, newVal) {
              fields.onHandle(e.target.name, newVal);
            }}
          />
        );
      })}
    </FormGroup>
  </FormControl>
);
export default renderGroupedCheckboxes;
the individual checkbox
    //renderCheckboxField
    
    import React from "react";
    import Checkbox from "@material-ui/core/Checkbox";
    import FormControl from "@material-ui/core/FormControl";
    import FormControlLabel from "@material-ui/core/FormControlLabel";
    import FormHelperText from "@material-ui/core/FormHelperText";
    
    const renderCheckboxField = ({
      input,
      rows,
      multiline,
      label,
      meta: { touched, error, warning }
    }) => (
      <FormControl component="fieldset">
        <FormControlLabel
          label={label}
          control={<Checkbox />}
          checked={input.value ? true : false}
          {...input}
        />
        <FormHelperText error={error && error.length > 0 ? true : false}>
          {(error && error.length > 0 ? error : null) ||
            (warning && warning.length > 0 ? warning : null)}
        </FormHelperText>
      </FormControl>
    );
export default renderCheckboxField;
                Modify renderGroupedCheckboxes.js. We are checking if any of the checkbox is touched and all the checkboxes are having error, then render the error text
import React from "react";
import { Field } from "redux-form";
import FormControl from "@material-ui/core/FormControl";
import FormLabel from "@material-ui/core/FormLabel";
import FormGroup from "@material-ui/core/FormGroup";
import FormHelperText from "@material-ui/core/FormHelperText";
import renderGroupedCheckboxField from "./renderGroupedCheckboxField";
const renderGroupedCheckboxes = (fields) => {
  let error = null;
  let isAnyFieldTouched = false;
  let isAllFieldsError = true;
  
  for (let name of fields.names) {
    //if touched is true for any one field, isAnyFieldTouched will
    //be true 
    isAnyFieldTouched = isAnyFieldTouched || fields[name].meta.touched;
    if (
      error === null &&
      fields[name].meta.error &&
      fields[name].meta.error.length > 0
    ) {
      error = fields[name].meta.error;
    }
    //if invalid is false for any one field, isAllFieldsError will
    //be false 
    isAllFieldsError = isAllFieldsError && fields[name].meta.invalid;
  }
  return (
    <FormControl component="fieldset" fullWidth={true}>
      <FormLabel component="legend">{fields.label}</FormLabel>
      <FormGroup row>
        {fields.names.map((item, j) => {
          return (
            <Field
              key={j}
              name={item}
              component={renderGroupedCheckboxField}
              label={fields.options[j].label}
              onChange={function (e, newVal) {
                fields.onHandle(e.target.name, newVal);
              }}
            />
          );
        })}
      </FormGroup>
        <FormHelperText error={error && error.length > 0 ? true : false}>
          {isAnyFieldTouched && isAllFieldsError && error && error.length > 0
            ? error
            : null}
        </FormHelperText>
    </FormControl>
  );
};
export default renderGroupedCheckboxes;
Create renderGroupedCheckboxField.js as below. The reason we are creating new file it to not impact current behavior of checkbox field.
import React from "react";
import Checkbox from "@material-ui/core/Checkbox";
import FormControl from "@material-ui/core/FormControl";
import FormControlLabel from "@material-ui/core/FormControlLabel";
const renderGroupedCheckboxField = ({
  input,
  rows,
  multiline,
  label,
  meta: { touched, error, warning }
}) => (
  <FormControl component="fieldset">
    <FormControlLabel
      label={label}
      control={<Checkbox />}
      checked={input.value ? true : false}
      {...input}
    />
  </FormControl>
);
export default renderGroupedCheckboxField;
sandbox - https://codesandbox.io/s/funny-fast-f3i12?file=/src/_SharedFormComponents/renderGroupedCheckboxes.js
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With