今天做了一個 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)}】`;
}
},
希望這篇文章能幫到遇到類似需求的同行~