antd 中对树形表格中二级元素进行筛选过滤
今天做了一个 antd 的表格,该表格是个树形表格,也就是一行中还有 children 元素作为子行。
如图所示:
需求要求对二级元素即 children 元素进行筛选,但是 antd 自身的 onFilter 并不能筛选 children。。。我也在网上查询了相关信息,并没查到有效的解决方案,相对有效的就是筛选的时候自己对 dataSource 进行过滤,但是这就会导致复杂度的增加。比如此方案我们就需要将后端返回的数据克隆一份,然后对此克隆数据进行过滤等操作。而且我这需求中还需要对后端返回的数据进行编辑,编辑的文件也是备份文件,那么编辑后还要将备份文件和源文件同步等操作。这就很蛋疼了。。。
不过最后还是通过一个比较简单的方法解决了此问题。
在对 dataSource 不进行删除就实现过滤功能,首先想到的就是如何能隐藏某一行,比如可以给 dataSource 中的每行添加一个 hidden 属性,通过判断此属性来决定这行是否显示。
在查询 antd 的文档后,终于发现了此方法,这样的功能可能比较少见,网上也没有能直接搜到的结果,其实就是通过设置 onRow 属性:
<Table
columns={departmentColumns}
dataSource={dataSource}
loading={loading}
expandIconColumnIndex={1}
pagination={false}
onRow={record => {
// 隐藏 hidden 为 true 的行
if (record.hidden) {
return {
style: { display: 'none' }
}
}
}}
/>
这个属性我之前也没用到过,而且文档中也只举例了几个事件绑定操作,我也是通过观察猜测实验后得出的方法:)
既然能隐藏某一行那就好说了,只需在进行筛选的时候先将所有元素先显示即 hidden: true,再在 onFilter 里对被过滤的元素隐藏即可。
const [filterValue, setFilterValue] = useState({ first: '', firstScore: '', second: '', secondScore: '' });
const onFilterChange = (type, v) => {
// 每次过滤的时候,都先将所有行的 hidden 改为 false
// 这里将所有改为 false,不用担心其它某列进行了筛选,把为 true 的给改到了。因为 antd 的 columns 中的 onFilter 会在每次重新渲染的时候都执行一遍
dataSource.forEach(item => {
item.hidden = false;
item.children.forEach(child => {
child.hidden = false;
});
})
setFilterValue({
...filterValue,
[type]: v
});
}
{
title: '得分【状态】',
dataIndex: 'secondScore',
filterDropdown: <FilterRadio
options={secondScoreLevelFilter}
value={filterValue.secondScore}
onChange={v => {
onFilterChange('secondScore', v);
}}
/>,
filteredValue: filterValue.secondScore ? [filterValue.secondScore] : null,
onFilter: (v, record) => {
// 二级过滤,只能通过给行添加 hidden: true,然后通过 Table 的 onRow 进行过滤
record.children.forEach(child => {
child.hidden = child.hidden || child.scoreLvl !== v; // 需要先判断下如果当前行 hidden 为 true 就直接返回。hidden 为 true 说明其它列的筛选将此行过滤了。
});
return record.children.find(item => item.scoreLvl === v);
},
render(v, record) {
return record.index ? null :`${getValue(record.score)}【${getValue(record.scoreLvl)}】`;
}
},
希望这篇文章能帮到遇到类似需求的同行~