2

guys I just used the Shahnawaz example here Handle multiple Checkboxed in a State:Array. How to? but stuck with multiple true IDs when clicking on names/categories with the same projects, for example, will give you duplicated project1 and project2 when checked === true for two categories.....

checked1 (english === true) will give you project1 , project2 checked2 (maths=== true) will give you project1 , project3 checked4 again project1 , project2 duplicated

Any ideas on how to work this out?

import React from "react";

const Checkbox = ({ type = "checkbox", name, checked = false, onChange }) => (
  <input type={type} name={name} checked={checked} onChange={onChange} />
);

const checkboxes = [
  {
    id: "31",
    category: "englsh",
    projects: [
      {
        id: "9",
      },
    ],
  },
  {
    id: "32",
    category: "maths",
    projects: [
      {
        id: "2",
      },
    ],
  },
  {
    id: "33",
    category: "marketing",
    projects: [
      {
        id: "2",
      },
    ],
  },
  {
    id: "34",
    category: "physics",
    projects: [
      {
        id: "2",
      },
    ],
  },
  {
    id: "35",
    category: "media ",
    projects: [
      {
        id: "2",
      },
      {
        id: "10",
      },
    ],
  },
  {
    id: "36",
    category: "science",
    projects: [
      {
        id: "9",
      },
      {
        id: "11",
      },
    ],
  },
];

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checkedItems: new Map(),
    };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const item = e.target.name;
    const isChecked = e.target.checked;
    console.log(item);
    console.log(isChecked);
    this.setState((prevState) => ({
      checkedItems: prevState.checkedItems.set(item, isChecked),
    }));
  }

  render() {
    return (
      <div className="row float-center d-flex justify-content-center">
        {checkboxes.map((item) => (
          <label key={item.key} className="m-3">
            <Checkbox
              name={item.name}
              checked={this.state.checkedItems.get(item.name)}
              onChange={this.handleChange}
            />
            {item.name}
          </label>
        ))}
      </div>
    );
  }
}
Shahnawaz Hossan
  • 2,695
  • 2
  • 13
  • 24
Sam
  • 23
  • 5

1 Answers1

1

As you want keys under name showing on the label, extract your key by doing this Object.keys(item.name)[0] rather than item.name. Also, pass an extra property(here index) so that you can print your desired values from the checkboxes array by the correct index. Here I've done that by using event.target.

Update:

If you want unique values, simply declare a state so that you can add items into that array(when checked) and remove items from that array(when unchecked). Finally, put your array in a set and you're done. Use Array.from() to convert the set into the array.

Here is the working code:

import React from "react";

const Checkbox = ({
  type = "checkbox",
  name,
  index,
  checked = false,
  onChange,
}) => (
  <input
    type={type}
    name={name}
    data-index={index}
    checked={checked}
    onChange={onChange}
  />
);

const checkboxes = [
  {
    name: { english: ["project1", "project2"] },
    key: "1",
    label: "1",
  },
  {
    name: { maths: ["project1", "project3"] },
    key: "2",
    label: "2",
  },
  {
    name: { physics: ["project4", "project5"] },
    key: "3",
    label: "3",
  },
  {
    name: { marketing: ["project1", "project2"] },
    key: "4",
    label: "4",
  },
];

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checkedItems: new Map(),
      checkedArrays: [],
    };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const item = e.target.name;
    const isChecked = e.target.checked;
    let [key, value] = Object.entries(
      checkboxes[e.target.dataset.index].name
    )[0];
    console.log(isChecked);
    console.log(key);
    var len = value.length;

    if (isChecked) {
      for (var i = 0; i < len; i++) {
        this.state.checkedArrays.push(value[i]);
      }
    } else {
      for (var i = 0; i < len; i++) {
        const index = this.state.checkedArrays.indexOf(value[i]);
        if (index > -1) {
          this.state.checkedArrays.splice(index, 1); // 2nd parameter means remove one item only
        }
      }
    }

    this.setState((prevState) => ({
      checkedItems: prevState.checkedItems.set(item, isChecked),
    }));

    console.log("Duplicated array");
    console.log(this.state.checkedArrays);
    var uniqueArray = Array.from(new Set(this.state.checkedArrays));
    console.log("Unique array");
    console.log(uniqueArray);
  }

  render() {
    return (
      <div className="row float-center d-flex justify-content-center">
        {checkboxes.map((item, index) => (
          <label key={item.key} className="m-3">
            <Checkbox
              name={Object.keys(item.name)[0]}
              index={index}
              checked={this.state.checkedItems.get(Object.keys(item.name)[0])}
              onChange={this.handleChange}
            />
            {Object.keys(item.name)[0]}
          </label>
        ))}
      </div>
    );
  }
}

2nd update based on the requirements

import React from "react";

const Checkbox = ({
  type = "checkbox",
  name,
  index,
  checked = false,
  onChange,
}) => (
  <input
    type={type}
    name={name}
    data-index={index}
    checked={checked}
    onChange={onChange}
  />
);

const checkboxes = [
  {
    id: "31",
    category: "englsh",
    projects: [
      {
        id: "9",
        title: "This is the title for id 9",
        description: "This is description for id 9",
      },
    ],
  },
  {
    id: "32",
    category: "maths",
    projects: [
      {
        id: "2",
        title: "This is the title for id 2",
        description: "This is description for id 2",
      },
    ],
  },
  {
    id: "33",
    category: "marketing",
    projects: [
      {
        id: "2",
        title: "This is the title for id 2",
        description: "This is description for id 2",
      },
    ],
  },
  {
    id: "34",
    category: "physics",
    projects: [
      {
        id: "2",
        title: "This is the title for id 2",
        description: "This is description for id 2",
      },
    ],
  },
  {
    id: "35",
    category: "media",
    projects: [
      {
        id: "2",
        title: "This is the title for id 2",
        description: "This is description for id 2",
      },
      {
        id: "10",
        title: "This is the title for id 10",
        description: "This is description for id 10",
      },
    ],
  },
  {
    id: "36",
    category: "science",
    projects: [
      {
        id: "9",
        title: "This is the title for id 9",
        description: "This is description for id 9",
      },
      {
        id: "11",
        title: "This is the title for id 11",
        description: "This is description for id 11",
      },
    ],
  },
];

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checkedItems: new Map(),
      checkedArrays: [],
    };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const item = e.target.name;
    const isChecked = e.target.checked;
    let value = Object.values(checkboxes[e.target.dataset.index].projects);
    console.log(isChecked);
    console.log(item);
    var len = value.length;

    if (isChecked) {
      for (var i = 0; i < len; i++) {
        this.state.checkedArrays.push(value[i]);
      }
    } else {
      for (var i = 0; i < len; i++) {
        let index = this.state.checkedArrays.findIndex(
          (x) => x.id === value[i].id
        );
        if (index > -1) {
          this.state.checkedArrays.splice(index, 1); // 2nd parameter means remove one item only
        }
      }
    }

    this.setState((prevState) => ({
      checkedItems: prevState.checkedItems.set(item, isChecked),
    }));

    console.log("Duplicated array");
    console.log(this.state.checkedArrays);

    var uniqueArray = this.state.checkedArrays.filter(function (elem) {
      return !this[elem.id] && (this[elem.id] = true);
    }, Object.create(null));

    console.log("Unique array");
    console.log(uniqueArray);
  }

  render() {
    return (
      <div className="row float-center d-flex justify-content-center">
        {checkboxes.map((item, index) => (
          <label key={item.id} className="m-3">
            <Checkbox
              name={item.category}
              index={index}
              checked={this.state.checkedItems.get(item.category)}
              onChange={this.handleChange}
            />
            {item.category}
          </label>
        ))}
      </div>
    );
  }
}
Shahnawaz Hossan
  • 2,695
  • 2
  • 13
  • 24