From 25eda833fbad6d86e28e70559e1a009fe6dd1812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E6=9C=A8=E5=89=91=E5=85=89?= <52249626+Mumujianguang@users.noreply.github.com> Date: Sat, 27 Jan 2024 22:11:54 +0800 Subject: [PATCH] fix(Table): the onFilter methods of column adds ability to filter children (#47170) --- components/table/InternalTable.tsx | 3 +- .../table/__tests__/Table.filter.test.tsx | 41 +++++++++++++++++++ components/table/hooks/useFilter/index.tsx | 30 ++++++++++---- 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/components/table/InternalTable.tsx b/components/table/InternalTable.tsx index 4ae04c5ca3..9e3b0c3f3c 100644 --- a/components/table/InternalTable.tsx +++ b/components/table/InternalTable.tsx @@ -289,6 +289,7 @@ const InternalTable = ( currentDataSource: getFilterData( getSortData(rawData, changeInfo.sorterStates!, childrenColumnName), changeInfo.filterStates!, + childrenColumnName, ), action, }); @@ -355,7 +356,7 @@ const InternalTable = ( getPopupContainer: getPopupContainer || getContextPopupContainer, rootClassName: classNames(rootClassName, rootCls), }); - const mergedData = getFilterData(sortedData, filterStates); + const mergedData = getFilterData(sortedData, filterStates, childrenColumnName); changeEventInfo.filters = filters; changeEventInfo.filterStates = filterStates; diff --git a/components/table/__tests__/Table.filter.test.tsx b/components/table/__tests__/Table.filter.test.tsx index 05970806bc..25c2b8f295 100644 --- a/components/table/__tests__/Table.filter.test.tsx +++ b/components/table/__tests__/Table.filter.test.tsx @@ -579,6 +579,47 @@ describe('Table.filter', () => { expect(container.querySelectorAll('tbody tr').length).toBe(4); }); + it('can filter children by defaultFilteredValue', async () => { + const { container } = render( + createTable({ + columns: [ + { + ...column, + defaultFilteredValue: ['Jim', 'Tom'], + onFilter: (value: string, record) => { + if (record.children && record.children.length) { + return true; + } + return record.name.includes(value); + }, + }, + ], + dataSource: [ + { + key: '0', + name: 'Jack', + children: [ + { key: '0-1', name: 'Jim' }, + { key: '0-2', name: 'Tony' }, + ], + }, + { key: '1', name: 'Lucy' }, + { key: '2', name: 'Tom' }, + { key: '3', name: 'Jerry' }, + ], + expandable: { + defaultExpandAllRows: true, + }, + }), + ); + + expect([...container.querySelectorAll('tbody tr')].map((item) => item.textContent)).toEqual([ + 'Jack', + 'Jim', + 'Tom', + ]); + }); + // Warning: An update to Item ran an effect, but was not wrapped in act(...). it('fires change event', () => { const handleChange = jest.fn(); diff --git a/components/table/hooks/useFilter/index.tsx b/components/table/hooks/useFilter/index.tsx index 7506cdf490..986d8ce410 100644 --- a/components/table/hooks/useFilter/index.tsx +++ b/components/table/hooks/useFilter/index.tsx @@ -157,6 +157,7 @@ function generateFilterInfo(filterStates: FilterState[]) export function getFilterData( data: RecordType[], filterStates: FilterState[], + childrenColumnName: string, ) { return filterStates.reduce((currentData, filterState) => { const { @@ -164,13 +165,28 @@ export function getFilterData( filteredKeys, } = filterState; if (onFilter && filteredKeys && filteredKeys.length) { - return currentData.filter((record) => - filteredKeys.some((key) => { - const keys = flattenKeys(filters); - const keyIndex = keys.findIndex((k) => String(k) === String(key)); - const realKey = keyIndex !== -1 ? keys[keyIndex] : key; - return onFilter(realKey, record); - }), + return ( + currentData + // shallow copy + .map((record) => ({ ...record })) + .filter((record: any) => + filteredKeys.some((key) => { + const keys = flattenKeys(filters); + const keyIndex = keys.findIndex((k) => String(k) === String(key)); + const realKey = keyIndex !== -1 ? keys[keyIndex] : key; + + // filter children + if (record[childrenColumnName]) { + record[childrenColumnName] = getFilterData( + record[childrenColumnName], + filterStates, + childrenColumnName, + ); + } + + return onFilter(realKey, record); + }), + ) ); } return currentData;