Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping checkboxes inside checkboxes ReactJS

I have a function which triggers children checkboxes once main checkbox is checked, and all these checkboxes are mapped from JSON. The main checkboxes (Highest level) and all of its children checkboxes (2nd level) under them are shown on click and its working great, what I am trying to display is the children of those children of the main checkboxes (3rd level) on clicking the 2nd level items.

Basically to show all three orders under each other on check, and add the 3rd order to my current code, so Options Group shows Options, and under Options is what I want to show, which are Option 1, Option 2, option 3 and so on..

The checkbox values are passed as props from Checkbox.js to Itemlist.js where the fetch/map happens.

(P.S. I have selection limit on each section in case anyone got confused about the selection process, which is not relevant to this question and can be ignored)

Main Snippet : https://codesandbox.io/embed/6jykwp3x6n?fontsize=14

The 3rd level targeted boxes for demonstration only: https://codesandbox.io/embed/o932z4yr6y?fontsize=14 ,

Checkbox.js

import React from "react";
import "./Checkbox.css";

class Checkboxes extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentData: 0,
      limit: 2,
      checked: false
    };
  }

  selectData(id, event) {
    let isSelected = event.currentTarget.checked;
    if (isSelected) {
      if (this.state.currentData < this.props.max) {
        this.setState({ currentData: this.state.currentData + 1 });
      } else {
        event.preventDefault();
        event.currentTarget.checked = false;
      }
    } else {
      if (this.state.currentData >= this.props.min) {
        this.setState({ currentData: this.state.currentData - 1 });
      } else {
        event.preventDefault();
        event.currentTarget.checked = true;
      }
    }
  }

  render() {
    const input2Checkboxes =
      this.props.options &&
      this.props.options.map(item => {
        return (
          <div className="inputGroup2">
            {" "}
            <div className="inputGroup">
              <input
                id={this.props.childk + (item.name || item.description)}
                name="checkbox"
                type="checkbox"
                onChange={this.selectData.bind(
                  this,
                  this.props.childk + (item.name || item.description)
                )}
              />
              <label
                htmlFor={this.props.childk + (item.name || item.description)}
              >
                {item.name || item.description}{" "}

              </label>
            </div>
          </div>
        );
      });

    return (
      <form className="form">
        <div>
          {/** <h2>{this.props.title}</h2>*/}
          <div className="inputGroup">
            <input
              id={this.props.childk + this.props.name}
              name="checkbox"
              type="checkbox"
              checked={this.state.checked}
              onChange={this.selectData.bind(
                this,
                this.props.childk + this.props.uniq
              )}
              onChange={() => {
                this.setState({
                  checked: !this.state.checked,
                  currentData: 0
                });
              }}
            />
            <label htmlFor={this.props.childk + this.props.name}>
              {this.props.name}{" "}
            </label>
          </div>{" "}
          {this.state.checked ? input2Checkboxes : undefined}
        </div>
      </form>
    );
  }
}

export default Checkboxes;

Itemlist.js Where the mapping function happen

...

      const selectedItem =
        selectedChild.children && selectedChild.children.length
          ? selectedChild.children[this.state.itemSelected]
          : null;

...

  <div>
                {selectedItem &&
                  selectedItem.children &&
                  selectedItem.children.map((item, index) => (
                    <Checkboxes
                      key={index}
                      name={item.name || item.description}
                      myKey={index}
                      options={item.children}
                      childk={item.id}
                      max={item.max}
                      min={item.min}
                    />
                  ))}
              </div>
...
like image 219
Laflm Avatar asked Mar 12 '19 22:03

Laflm


1 Answers

The issue is a recursive one. When an options group is displayed, the group checkbox and its options are displayed. When displaying the options, their type has to be taken into account.

  1. If the option is an ingredient, a simple checkbox can be displayed.
  2. If it is a group, a new options group has to be displayed with its options, like discribed above.

This is what is missing in your code. Here is a working sandbox and here is how you can fix it:

in Checkbox.js:

const input2Checkboxes =
  this.props.options &&
  this.props.options.map((item, index) => {
    // Is the option a 'group' or an 'ingredient'?
    return item.type === "group" ? (
      {/* It's a group so display its options recursively */}
      <Checkboxes
        key={index}
        name={item.name || item.description}
        options={item.children}
        childk={this.props.childk}
        max={item.max}
        min={item.min}
      />
    ) : (
      {/* It's an ingredient so display a simple checkbox */}
      <div className="inputGroup2" key={item.name || item.description}>
        {" "}
        <div className="inputGroup">
          <input
            id={this.props.childk + (item.name || item.description)}
            name="checkbox"
            type="checkbox"
            onChange={this.selectData.bind(
              this,
              this.props.childk + (item.name || item.description)
            )}
          />
          <label
            htmlFor={this.props.childk + (item.name || item.description)}
          >
            {item.name || item.description}{" "}
          </label>
        </div>
      </div>
    );
  });
like image 156
Baboo Avatar answered Nov 11 '22 06:11

Baboo