泗陽(yáng)做網(wǎng)站公司競(jìng)價(jià)托管就選微競(jìng)價(jià)
React Antd ProTable 如何設(shè)置類似于Excel的篩選框
目標(biāo):在web頁(yè)面的table表格中完成類似于EXCEL的Filter篩選功能。
示例圖:點(diǎn)擊標(biāo)題列上方的漏斗狀圖標(biāo),即可對(duì)數(shù)據(jù)進(jìn)行篩選。
ProTable 前景提要
ProTable API中有說(shuō)明,是有filter篩選功能的
參數(shù) | 說(shuō)明 | 類型 | 默認(rèn)值 | 版本 |
---|---|---|---|---|
filters | 表頭的篩選菜單項(xiàng) | object[] | - | - |
onFilter | 本地模式下,確定篩選的運(yùn)行函數(shù) | function | - | - |
個(gè)人理解:
filters 設(shè)置被篩選的數(shù)據(jù)
,數(shù)據(jù)形式是object
onFilter 設(shè)置篩選的函數(shù)方法
就是自定義一個(gè)函數(shù)方法用于篩選
理論階段
根據(jù) 前景提要可知,設(shè)置篩選需要兩個(gè)設(shè)置。
1.數(shù)據(jù)準(zhǔn)備
-
既然要篩選,那必須是所有數(shù)據(jù)在里面,且是去除重復(fù)后的數(shù)據(jù)。這樣子才算篩選。
那重點(diǎn)就是數(shù)據(jù)去重
,存儲(chǔ)
了 -
可以看到我是有多列需要篩選,那還是抽象封裝一個(gè)方法數(shù)據(jù)
去重,和存儲(chǔ)的方法
來(lái)調(diào)用方便低調(diào)用和維護(hù)。
2.篩選函數(shù)
-
就是你選擇了篩選框的數(shù)據(jù),你要自定義匹配方式,成功就是true,失敗就是false。
頁(yè)面就會(huì)顯示匹配成功的數(shù)據(jù)。 -
也是封裝方法都用這個(gè)匹配方法即可
實(shí)踐階段
1.數(shù)據(jù)準(zhǔn)備
- 首先在ProTable中使用request獲取數(shù)據(jù),調(diào)用生成數(shù)據(jù)方法
request={async (params, sorter, filter) => {const r = await queryData(current_table, { ...params, sorter, filter });//獲取的數(shù)據(jù)為r,若有數(shù)據(jù)則,生成篩選數(shù)據(jù)。if (r?.data) {generateFilterOptions(r.data, {period: 'period',end_customer: 'end_customer',customer_name: 'customer_name',});}
- 編寫生成數(shù)據(jù)方法generateFilterOptions
/**
3. data 原數(shù)據(jù) propertyMappings 篩選模板*/function generateFilterOptions(data: any[],propertyMappings: { [key: string]: string },handleNullForKeys?: string[],): void {const groupedOptions: { [key: string]: Option[] } = {};// 遍歷數(shù)據(jù),直接構(gòu)建分組選項(xiàng)data.forEach((item) => {Object.entries(propertyMappings).forEach(([targetKey, sourceKey]) => {let value = item[sourceKey];if (handleNullForKeys?.includes(targetKey) && value === null) value = '';if (!groupedOptions[targetKey]) {groupedOptions[targetKey] = [];}// 確保每個(gè)值只添加一次,利用 Set 去重const valueSet = new Set(groupedOptions[targetKey].map((option) => option.value));if (!valueSet.has(value)) {groupedOptions[targetKey].push({ key: targetKey, text: String(value), value });}});});// 將生成的選項(xiàng)設(shè)置到狀態(tài)中setFilterOptions(groupedOptions);}
- 用useState存儲(chǔ)數(shù)據(jù)
const [filterOptions, setFilterOptions] = useState<{ [key: string]: Option[] }>({});
- 可以看一下groupedOptions的數(shù)據(jù)格式,最后需要的就是
{text:‘2023-01’,value:‘2023-01’} 前面的key是用于不同列分組的
2.準(zhǔn)備篩選函數(shù)
// 通用的過(guò)濾函數(shù)const genericOnFilter = (dataIndex: string) => (value: any, record: any) => {if (value !== null) {if (value === '') {return record[dataIndex] === '';}if (record[dataIndex] !== null && (typeof value === 'string' || typeof value === 'number')) {return String(record[dataIndex]).indexOf(String(value)) === 0;}} else {return record[dataIndex] === null;}return false;};
因?yàn)閚ull可能或出錯(cuò),還有空字符串不能使用indexof所以寫出這樣。
value 是篩選選中的數(shù)據(jù),record[dataIndex]是列的數(shù)據(jù).
匹配上需要顯示的數(shù)據(jù)就返回true
,不需要的就返回false
3.開始使用
上面所說(shuō)的API都是ProTable 的column API
const columns: ProColumns<UserDetails>[] = [{title: 'Period',dataIndex: 'period',filters: filterOptions['period'],onFilter: genericOnFilter('period'),},{title: 'End Customer',dataIndex: 'end_customer',filters: filterOptions['end_customer'],onFilter: genericOnFilter('end_customer'),},{title: 'Customer name',dataIndex: 'customer_name',filters: filterOptions['customer_name'],onFilter: genericOnFilter('customer_name'),},.....
結(jié)束
理論上應(yīng)該講完了,可能還有更方便快捷的方法。
有疑問(wèn)或想法可以評(píng)論區(qū)留言。