繁体   English   中英

我需要修复 antd 树组件中的复选框选择问题

[英]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>
  );
};

CodeSandBox 链接

这就是错误所在_.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM