Reputation: 11
I have several checkbox groups on my Component
of which only one of the should be selected. Each group has the same number of checkboxes (3 in the example), and the one selected is identified by the checked
key inside the data
list.
How can I handle this state?
class test extends Component {
constructor(props) {
super(props);
this.state = {};
const data = [
{ name: orange, checked: 2 },
{ name: apple, checked: 3 },
{ name: banana, checked: 1 }
];
}
render() {
return (
<>
{data.map(items => (
<tr>
<td>{items.name}</td>
<td>
<div>
<input type="checkbox" value="1" checked={true} />
</div>
</td>
<td>
<div>
<input type="checkbox" value="2" checked={false} />
</div>
</td>
<td>
<div>
<input type="checkbox" value="3" checked={false} />
</div>
</td>
</tr>
))}
</>
);
}
}
Upvotes: 1
Views: 4309
Reputation: 2540
You can check at the checked
option if the value
of the checkbox is the same as the checked
value of your item
interface. Check this component as an example:
function CheckboxGroupRow({ name, checked, onUpdate }) {
return (
<tr className="CheckboxGroup">
<td>{name}</td>
<td>
<input
type="checkbox"
value={1}
checked={checked === 1}
onChange={e => onUpdate({ name, checked: +e.target.value })}
/>
</td>
<td>
<input
type="checkbox"
value={2}
checked={checked === 2}
onChange={e => onUpdate({ name, checked: +e.target.value })}
/>
</td>
<td>
<input
type="checkbox"
value={3}
checked={checked === 3}
onChange={e => onUpdate({ name, checked: +e.target.value })}
/>
</td>
</tr>
);
}
Each checkbox has a value
, and it's checked only if the value of the checked
variable matches to the one on the checkbox. For the onChange
handle I have an onUpdate
function that will be called with an updated data
item whenever a user clicks a checkbox
. Some logic upstream should handle the update.
Please take a look at this example build on CodeSandbox:
https://codesandbox.io/embed/checkboxgroup-cyv4p
I hope it helps
Upvotes: 2
Reputation: 15698
Try organizing your data-structure to look something like this:
data: [
{ name: "orange", boxes: [1, 2, 3], selected: null },
{ name: "apple", boxes: [1, 2, 3], selected: null },
{ name: "pineapple", boxes: [1, 2, 3], selected: null }
]
That gives us a group-name, an array of values to choose from and a selected value. We'll be manipulating that data via our component-state.
Here's a codesandbox for reference: https://codesandbox.io/s/gallant-paper-b1d4z
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{ name: "orange", boxes: [1, 2, 3], selected: null },
{ name: "apple", boxes: [1, 2, 3], selected: null },
{ name: "pineapple", boxes: [1, 2, 3], selected: null }
]
};
}
handleOnChange = e => {
const { data } = this.state;
const { name, value } = e.target;
const updatedData = data.map(group => {
if (group.name === name) {
return {
...group,
selected: group.selected === value ? null : value
};
} else {
return group;
}
});
this.setState({ data: updatedData }, () => console.log(this.state));
};
createInputGroups = () => {
const { data } = this.state;
const groups = data.map(group => {
return (
<div style={{ display: "flex" }}>
<div>{group.name}</div>
<div>
{group.boxes.map(box => {
return (
<input
onChange={this.handleOnChange}
type="checkbox"
name={group.name}
value={box}
checked={group.selected == box}
/>
);
})}
</div>
</div>
);
});
return groups;
};
render() {
return <div>{this.createInputGroups()}</div>;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Pleases excuse my CSS :)
Upvotes: 4