antd Transfer树穿梭框父子节点关联,支持全选、搜索,右侧只展示子节点

import { Transfer, Tree } from 'antd';
import React, { useState, useEffect } from 'react';

const generateTree = (treeNodes = [], checkedKeys = []) =>
  treeNodes.map(({ children, ...props }) => ({
    ...props,
    disabled: checkedKeys.includes(props.key),
    children: generateTree(children, checkedKeys),
  }));

const TreeTransferComp = ({ dataSource, targetKeys, ...restProps }) => {
  const [newDataSource, setNewDataSource] = useState([]);

  useEffect(() => {
    setNewDataSource(dataSource);
  }, [dataSource]);

  const transferDataSource = [];
  function flatten(list = []) {
    list.forEach((item) => {
      transferDataSource.push(item);
      flatten(item.children);
    });
  }
  flatten(dataSource);

  // 树搜索函数 
  const onsearchDataSource = (dataSource, val) => {
    // 递归查找存在的父级
    const deepFilter = (i, val) => {
      return (
        i.children.filter((o) => {
          if (o.title.indexOf(val) > -1) {
            return true;
          }
          if (o.children && o.children.length > 0) {
            return deepFilter(o, val);
          }
        }).length > 0
      );
    };
    const filterMenu = (list, val) => {
      return list
        .filter((item) => {
          if (item.title.indexOf(val) > -1) {
            return true;
          }
          if (item.children && item.children.length > 0) {
            return deepFilter(item, val);
          }
          return false;
        })
        .map((item) => {
          item = Object.assign({}, item);
          if (item.children) {
            item.children = item.children.filter((res) => res.title.indexOf(val) > -1);
            filterMenu(item.children, val);
          }
          return item;
        });
    };
    return filterMenu(dataSource, val);
  }

  const dealCheckboxSeleted = ({ e, onItemSelect, onItemSelectAll }, direction) => {
    let {
      checked,
      halfCheckedKeys,
      node: { key, children },
    } = e;

    // 勾选的是父节点
    if (children?.length > 0) {
      let keys = [];
      if (direction === 'left') {
        children?.forEach(child => {
          keys.push(child.key)
        });
        onItemSelectAll([...keys, key], checked);
      }
      if (direction === 'right') {
        children?.forEach(child => {
          keys.push(child.key)
        });
        onItemSelectAll([...keys], checked);
      }
    } else {
      // 勾选的是子节点
      if (!checked) {
        // 查找该元素的父元素
        let parentKeys = [];
        parentKeys = [halfCheckedKeys?.[0]] || [];
        if (parentKeys[0] == undefined) {
          // 当一级下的二级全部取消勾选,一级也取消勾选
          dataSource.forEach(tree => {
            if (tree.children) {
              tree.children?.forEach(child => {
                if (child?.key === key) {
                  parentKeys.push(tree?.key)
                }
              })
            }
          });
        }
        onItemSelectAll([...parentKeys, key], checked)
      } else {
        let parentKey = '';
        dataSource.forEach(tree => {
          if (tree?.children) {
            tree.children?.forEach(child => {
              if (child?.key === key) {
                parentKey = tree?.key;
              }
            });
          }
        });
        if (!halfCheckedKeys?.includes(parentKey) && parentKey != '') {
          onItemSelectAll([key, parentKey], checked);
        } else {
          onItemSelect(key, checked);
        }
      }
    }
  };

  return (
    <Transfer
      titles={['分组', '仅展示子节点']}
      {...restProps}
      targetKeys={targetKeys}
      dataSource={transferDataSource}
      className="tree-transfer"
      render={(item) => item.title}
      showSelectAll={true}
      showSearch
      onSearch={(dir, val) => {
        if (dir === 'left') { // 左边搜索
          if (val !== '') {
            const newDeptList = onsearchDataSource(dataSource, val);
            setNewDataSource(newDeptList);
          } else {
            setNewDataSource(dataSource);// 左边没搜索时候的原始数据
          }
        }
      }}
    >
      {({ direction, onItemSelect, selectedKeys, onItemSelectAll }) => {
        if (direction === 'left') {
          const checkedKeys = [...selectedKeys, ...targetKeys];
          return (
            <Tree
              blockNode
              checkable
              defaultExpandAll
              checkedKeys={checkedKeys}
              treeData={generateTree(newDataSource, targetKeys)}
              onCheck={(_, e) => {
                dealCheckboxSeleted({ e, onItemSelect, onItemSelectAll }, direction)
              }}
              onSelect={(_, e) => {
                dealCheckboxSeleted({ e, onItemSelect, onItemSelectAll }, direction)
              }}
            />
          );
        }
      }}
    </Transfer>
  );
};

export default TreeTransferComp;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值