[英]I need to fix checkbox selection issue in antd tree component
我正在使用一个 antd 树组件 我根据我的用例自定义了一些代码 我在一个父复选框下有一个子列表 如果我在该父列表下选择父所有会发生什么得到检查但我也显示了列表的计数在子项的每个父列表中,因此如果我选择监视列表,则每个复选框都会被选中,但是如果我单击该特定子数据列表,则子复选框列表计数不会更新,那么计数将得到更新,但如果我取消选中父监视列表,则只有数据列表不会取消选中,如果我单击父项,那么我需要在所有列表下更新这两种情况的子项计数在下面添加了完整的代码沙盒链接...
this is my oncheck code that perform check uncheck
const onCheck = React.useCallback(
(checkedKeysValue, e) => {
if (e.checked) {
if (e.node?.children?.length) {
setCheckedKeys(
_.union(
checkedKeys,
_.cloneDeep([...e.node.children.map((child) => child.key)])
)
);
} else {
setCheckedKeys(_.union(checkedKeys, [e.node.key]));
}
} else {
if (e.node?.children?.length) {
setCheckedKeys(
_.union(
checkedKeys.filter((item) => {
return (
item !== e.node.key &&
!e.node.children.filter((child) => child.key === item).length
);
})
)
);
} else {
setCheckedKeys(
_.cloneDeep(checkedKeys.filter((item) => item !== e.node.key))
);
}
}
},
[checkedKeys, setCheckedKeys]
);
const Demo = ({ alterCountsCalculation = {} }) => {
const [expandedKeys, setExpandedKeys] = useState([]);
const [checkedKeys, setCheckedKeys] = useState([]);
const [selectedKeys, setSelectedKeys] = useState([]);
const [autoExpandParent, setAutoExpandParent] = useState(true);
const [searchValue, setSearchValue] = useState("");
const [checkedKeysCount, setCheckedKeysCount] = useState(0);
const [tree, setTree] = useState(treeData);
const onExpand = (expandedKeysValue) => {
console.log("onExpand", expandedKeysValue); // if not set autoExpandParent to false, if children expanded, parent can not collapse.
// or, you can remove all expanded children keys.
setExpandedKeys(expandedKeysValue);
setAutoExpandParent(false);
};
React.useEffect(() => {
let alteredCount = 0;
let count = checkedKeys.filter((item) => {
if (Object.keys(alterCountsCalculation).includes(item)) {
alteredCount = alteredCount + alterCountsCalculation[item];
return false;
}
return !treeData.filter((node) => node.title == item).length;
}).length;
setCheckedKeysCount(count + alteredCount);
}, [checkedKeys, treeData, alterCountsCalculation]);
const onCheck = React.useCallback(
(checkedKeysValue, e) => {
if (e.checked) {
if (e.node?.children?.length) {
setCheckedKeys(
_.union(
checkedKeys,
_.cloneDeep([...e.node.children.map((child) => child.key)])
)
);
} else {
setCheckedKeys(_.union(checkedKeys, [e.node.key]));
}
} else {
if (e.node?.children?.length) {
setCheckedKeys(
_.union(
checkedKeys.filter((item) => {
return (
item !== e.node.key &&
!e.node.children.filter((child) => child.key === item).length
);
})
)
);
} else {
setCheckedKeys(
_.cloneDeep(checkedKeys.filter((item) => item !== e.node.key))
);
}
}
},
[checkedKeys, setCheckedKeys]
);
const onSelect = (selectedKeysValue, info) => {
console.log("onSelect", info);
setSelectedKeys(selectedKeysValue);
};
React.useEffect(() => {
const checked = [];
treeData.forEach((data) => {
data.children.forEach((item) => {
if (item.checked) {
checked.push(item.key);
}
});
});
setCheckedKeys(checked);
}, []);
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
React.useEffect(() => {
if (searchValue) {
const filteredData = filteredTreeData(
treeData,
searchValue,
checkedKeys,
setExpandedKeys
);
setTree([...filteredData]);
} else {
setTree(treeData);
}
}, [searchValue, checkedKeys]);
return (
<div>
{JSON.stringify(checkedKeysCount)}
<Search
style={{ marginBottom: 8 }}
placeholder="Search"
onChange={(e) => {
setSearchValue(e.target.value);
}}
/>
<Tree
checkable
onExpand={onExpand}
titleRender={(nodeData) => {
const index = nodeData.title
.toLowerCase()
.indexOf(searchValue.toLowerCase());
const beforeStr = nodeData.title.substr(0, index);
const afterStr = nodeData.title.substr(index + searchValue?.length);
const searchedString = nodeData.title.substr(
index,
searchValue?.length
);
let countSelectedChilds = 0;
if (nodeData.children?.length) {
nodeData.children.forEach((child) => {
if (checkedKeys?.includes(child.key)) {
countSelectedChilds++;
}
});
}
return index > -1 ? (
<span>
{beforeStr}
<span className="site-tree-search-value">
{searchedString}
</span>{" "}
{afterStr}{" "}
{countSelectedChilds ? <span>({countSelectedChilds})</span> : ""}
</span>
) : (
<span>{nodeData.title}</span>
);
}}
autoExpandParent={true}
onCheck={onCheck}
checkedKeys={checkedKeys}
expandedKeys={expandedKeys}
treeData={tree}
/>
</div>
);
};
这就是错误所在_.cloneDeep([...e.node.children.map((child) => child.key)])
和这里
checkedKeys.filter((item) => {
return (
item !== e.node.key &&
!e.node.children.filter((child) => child.key === item).length
);
});
在这两个地方,您都在添加键并过滤node
的直接子级的键,但是children of children
呢? 它们也需要添加和过滤。
试试这个:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Tree, Input } from "antd";
import * as _ from "lodash";
const { Search } = Input;
const treeData = [
{
title: "Watchlists",
key: "Watchlists",
children: [
{
title: "Data List",
key: "Data List",
checked: true,
children: [
{ title: "Open Data", key: "Open Data", checked: true },
{
title: "trade",
key: "trade",
checked: true
},
{
title: "List",
key: "List",
checked: true
},
{ title: "Daily", key: "Daily", checked: true }
]
},
{
title: "Department and trade",
key: "Department and trade",
checked: true
},
{
title: "North List",
key: "North List",
checked: true
},
{ title: "People's Daily", key: "People's Daily", checked: true }
]
},
{
title: "Af Watchlists",
key: "Af Watchlists",
children: [
{
title: "Service Wanted List",
key: "Service Wanted List",
checked: true
}
]
},
{
title: "EM Watchlists",
key: "EM Watchlists",
children: [
{
title: "National Financing",
key: "National Financing",
checked: true
},
{
title: "Arabia List",
key: "Arabia List",
checked: true
}
]
},
{
title: "Assets List",
key: "Assets List",
children: [
{
title: "National List",
key: "National List",
checked: true
}
]
},
{
title: "New Watchlists",
key: "New Watchlists",
children: [
{ title: "FATR", key: "FATR", checked: true },
{ title: "Internal", key: "Internal", checked: true },
{
title: "OC List (Covers 73 Lists)",
key: "OC List (Covers 73 Lists)",
checked: true
},
{ title: "UN", key: "UN", checked: true },
{
title: "Security List (Covers 18 Lists)",
key: "Security List (Covers 18 Lists)",
checked: true
}
]
}
];
const hasSearchTerm = (n, searchTerm) =>
n.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1;
const filterData = (arr, searchTerm) =>
arr?.filter(
(n) =>
hasSearchTerm(n.title, searchTerm) ||
filterData(n.children, searchTerm)?.length > 0
);
function filteredTreeData(data, searchString, checkedKeys, setExpandedTree) {
let keysToExpand = [];
const filteredData = searchString
? filterData(data, searchString).map((n) => {
keysToExpand.push(n.key);
return {
...n,
children: filterData(n.children, searchString, checkedKeys)
};
})
: data;
setExpandedTree([...keysToExpand]);
return filteredData;
}
const Demo = ({ alterCountsCalculation = {} }) => {
const [expandedKeys, setExpandedKeys] = useState([]);
const [checkedKeys, setCheckedKeys] = useState([]);
const [selectedKeys, setSelectedKeys] = useState([]);
const [autoExpandParent, setAutoExpandParent] = useState(true);
const [searchValue, setSearchValue] = useState("");
const [checkedKeysCount, setCheckedKeysCount] = useState(0);
const [tree, setTree] = useState(treeData);
const onExpand = (expandedKeysValue) => {
console.log("onExpand", expandedKeysValue);
setExpandedKeys(expandedKeysValue);
setAutoExpandParent(false);
};
React.useEffect(() => {
let alteredCount = 0;
let count = checkedKeys.filter((item) => {
if (Object.keys(alterCountsCalculation).includes(item)) {
alteredCount = alteredCount + alterCountsCalculation[item];
return false;
}
return !treeData.filter((node) => node.title === item).length;
}).length;
setCheckedKeysCount(count + alteredCount);
}, [checkedKeys, alterCountsCalculation]);
function getKeyValues(nodeChildren) {
let keys = [];
nodeChildren.forEach((child) => {
if (child?.children?.length) {
keys = [...keys, ...getKeyValues(child.children)];
}
keys = [...keys, child.key];
});
return keys;
}
const onCheck = React.useCallback(
(checkedKeysValue, e) => {
if (e.checked) {
if (e.node?.children?.length) {
const keys = [...getKeyValues(e.node.children)];
setCheckedKeys(
_.union(checkedKeys, _.cloneDeep([...keys, e.node.key]))
);
} else {
setCheckedKeys(_.union(checkedKeys, [e.node.key]));
}
} else {
if (e.node?.children?.length) {
const keys = getKeyValues(e.node.children);
setCheckedKeys(
_.union(
checkedKeys.filter((item) => {
return item !== e.node.key && !keys.includes(item);
})
)
);
} else {
setCheckedKeys(
_.cloneDeep(checkedKeys.filter((item) => item !== e.node.key))
);
}
}
},
[checkedKeys, setCheckedKeys]
);
console.log(checkedKeys);
const onSelect = (selectedKeysValue, info) => {
console.log("onSelect", info);
setSelectedKeys(selectedKeysValue);
};
React.useEffect(() => {
let checked = [];
treeData.forEach((data) => {
data.children.forEach((item) => {
if (item.checked) {
checked.push(item.key);
if (item.children) {
checked = [...checked, ...item.children.map((child) => child.key)];
}
}
});
});
setCheckedKeys(checked);
}, []);
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
React.useEffect(() => {
if (searchValue) {
const filteredData = filteredTreeData(
treeData,
searchValue,
checkedKeys,
setExpandedKeys
);
setTree([...filteredData]);
} else {
setTree(treeData);
}
}, [searchValue, checkedKeys]);
return (
<div>
{JSON.stringify(checkedKeysCount)}
<Search
style={{ marginBottom: 8 }}
placeholder="Search"
onChange={(e) => {
setSearchValue(e.target.value);
}}
/>
<Tree
checkable
onExpand={onExpand}
titleRender={(nodeData) => {
const index = nodeData.title
.toLowerCase()
.indexOf(searchValue.toLowerCase());
const beforeStr = nodeData.title.substr(0, index);
const afterStr = nodeData.title.substr(index + searchValue?.length);
const searchedString = nodeData.title.substr(
index,
searchValue?.length
);
let countSelectedChilds = 0;
if (nodeData.children?.length) {
nodeData.children.forEach((child) => {
if (checkedKeys?.includes(child.key)) {
countSelectedChilds++;
}
});
}
return index > -1 ? (
<span>
{beforeStr}
<span className="site-tree-search-value">
{searchedString}
</span>{" "}
{afterStr}{" "}
{countSelectedChilds ? <span>({countSelectedChilds})</span> : ""}
</span>
) : (
<span>{nodeData.title}</span>
);
}}
autoExpandParent={true}
onCheck={onCheck}
// checkedKeys={checkedList ? checkedList : checkedKeys}
checkedKeys={checkedKeys}
expandedKeys={expandedKeys}
treeData={tree}
/>
</div>
);
};
ReactDOM.render(<Demo />, document.getElementById("container"));
在这里, getKeyValues
函数递归地计算key
数组,然后使用它来添加或删除checkedKeys
状态。
这是沙盒链接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.