一、问题描述
antd自带树形过滤有两个问题:
① 搜索仅仅加粗了筛选项,没有过滤其他项,若选项较多就不方便
② 确定按钮,只能在当前表内筛选,不可调用自己api接口,无法重新获取数据
二、解决思路
封装组件,挂载到filterDropDown属性下
三、编码
1、封装树形下拉组件
import {FilterDropdownProps} from 'antd/lib/table/interface';
import {
Button,
Divider,
Tree ,
Input,
} from 'antd';
import styles from './index.less';
import { Key } from 'react';
import { useState, useMemo} from 'react';
import { DataNode } from 'antd/lib/tree';
interface Props extends FilterDropdownProps{
onSearch:(value:string[])=>void;
multiple: boolean;
}
const TableTreeFilter:React.VFC<Props>=(prop)=>{
const {
setSelectedKeys,
selectedKeys,
filters,
confirm,
clearFilters,
multiple
} = props;
const [treeData,setTreeData] = useState<DataNode[]>([]);
const [treelist, setTreeList] = useState<DataNode[]>([]);
//初始化树
useMemo(() =>{
const loop = (data: DataNode[]): DataNode[] => {
data.map((item) => {
const title = item.title;
if(item.children) {
return {
title,
key:item.key,
children:loop(item.children),
disabled: item.disabled ? true : false,
};
}
return {
title,
key: item.key,
disabled:item.disabled ? true : false,
};
});
setTreeData(loop(filters));
setTreeList(loop(filters));
},[]);
//多选选中节点
const onCheck = (checkValues:Key[]) =>{
setSelectedKeys(checkValues);
}
//单选选中节点
const onSelect = (value:Key[]) =>{
setSelectedKeys(value);
}
//重置清空选中
const clear = () =>{
setSelctedKeys([]);
clearFilters;
}
//【确定】并关闭搜索树返回选中项到表内筛选
const onOk = () =>{
props.onSearch(slectedKeys as string[]);
confirm();
}
//过滤树节点
const filterTreeNodes = (
treeNodes:DataNode[],
search:string
):DataNode[] => {
const isMatched = (treeNode: DataNode, search: string):boolean=>{
return (
treeNode?.title.includes(search) ||
treeNode?.children?.some((node) => {
return isMatched(node,search)
})
);
};
return treeNodes
.map((node) =>{
if(isMatched(node, search)){
return {
...node,
children:node.children
? filterTreeNodes(node.children, search)
: [],
};
} else {
return [];
}
})
.flat();
};
//在树内搜索过滤项
const onTreeSearch = (e:any) =>{
const { value } = e.target;
const newTree = filterTreeNodes(treeList, value);
setTreeData(newTree);
}
return (
<div className={styles.filterContent}>
<Input
placeholder="请输入"
style={{ width: 210, margin: 10}}
onChange={onTreeSearch}
/>
<Divider />
<Tree
className={{styles.tree}}
defaultExpandALl
showIcon
checkable=(multiple]
//@ts- ignore
onCheck={onCheck}
onSelect={onSelect}
selectedKeys={selectedKeys}
checkedKeys={selectedKeys}
//@ts - ignore
treeData={treeData}
/>
<Divider />
<div className={styles.footer}>
<Button
size="small"
disabled={!selectedKeys?.length}
onClick={clear}
style={{float:"left"}}
>
重置
</Button>
<Button
type="primary"
size="small"
onClick={onOk}
style={{float:"right"}}
>
重置
</Button>
</div>
</div>
);
};
export default TableTreeFilter;
2、在table中调用
const TreeList:TreeNode[] = [
{
text: 'Joe',
value: '0',
},
{
text: 'Category 1',
value: '1',
children: [
{
text: 'Yellow',
value: '11',
},
{
text: 'Pink',
value: '12',
},
],
},
]
const columns: ColumnsType<DataType> = [
{
title: 'Name',
dataIndex: 'name',
filters: TreeList,
filterDropDown:(props)=>{
/**props是antd自带的一些属性,详情可见官网*/
<TableTreeFilter
{...props}
onSearch={(value)=>{
console.log(value);
/**此回调函数,返回的value就是选中值,可做为table的筛选条件*/
/**可在此处调用api接口*/
}}
/**可由此参数设置树结构为单选或者多选*/
multiple={false}
/>
},
width: 120,
},
]