Reputation: 367
I want to select a group based checkbox. The problem is that when I click on the group, the entire checkbox is selected. I don't want to select the entire checkbox. this is my Initial State.
const plainOptions = ["can_view", "can_create", "can_update"];
state = {
checkedList: [],
indeterminate: true,
checkAll: false
};
Method: onchange
method basically works each individual checkbox.
onChange = checkedList => {
console.log(checkedList);
this.setState({
checkedList,
indeterminate:
!!checkedList.length && checkedList.length < plainOptions.length,
checkAll: checkedList.length === plainOptions.length
});
};
This method works for selected all checkbox
onCheckAllChange = e => {
console.log(e.target.checked);
this.setState({
checkedList: e.target.checked ? plainOptions : [],
indeterminate: false,
checkAll: e.target.checked
});
};
{
["group", "topGroup"].map(item => (
<div className="site-checkbox-all-wrapper">
<Checkbox
indeterminate={this.state.indeterminate}
onChange={this.onCheckAllChange}
checked={this.state.checkAll}
>
{item}
</Checkbox>
<CheckboxGroup
options={plainOptions}
value={this.state.checkedList}
onChange={this.onChange}
/>
</div>
));
}
However, my accepted Data format is
{group:["can_view","can_create"],topGroup:["can_view","can_create"}
I want to get this format output when user selected on the checkbox
Here is the code sandbox : https://codesandbox.io/s/agitated-sea-1ygqu
Upvotes: 0
Views: 516
Reputation: 21150
The reason both groups change when you click something in one of them is because both groups use the same internal state.
["group", "topGroup"].map(item => (
<div className="site-checkbox-all-wrapper">
<Checkbox
indeterminate={this.state.indeterminate}
onChange={this.onCheckAllChange}
checked={this.state.checkAll}
>
{item}
</Checkbox>
<CheckboxGroup
options={plainOptions}
value={this.state.checkedList}
onChange={this.onChange}
/>
</div>
));
Both the group
and topGroup
use the same this.state.checkList
state.
The easiest way to solve this is by extracting each group into its own component. This way they have their own state separate of each other.
You could also opt to keep one component, but you must manage multiple internal states. You could for example use state = { checkList: [[], []] }
where the first sub-array is to store the group
state and the second sub-array is to store the topGroup
state.
If groups are dynamic you can simply map
over the groups and create your states that way:
state = { checkList: groups.map(() => []) };
You would also need to manage multiple indeterminate
and checkAll
states. This can be avoided when you deduce those from the checkList
state. For example:
isIndeterminate(index) {
const checkList = this.state.checkList[index];
return checkList.length > 0 && checkList.length < plainOptions.length;
}
This would also avoid conflicting state, since there is one source of truth.
Upvotes: 1