From 2c56927ae9c5cb88e9c77a90245192b7c2fb4fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=91=E9=9B=A8?= Date: Fri, 25 Feb 2022 16:05:18 +0800 Subject: [PATCH] feat: table filterSearch supports function (#34085) * feat: table filterSearch supports function * feat: update for test * feat: update document --- .../table/__tests__/Table.filter.test.js | 42 + .../__snapshots__/demo-extend.test.ts.snap | 823 ++++++++++++++++++ .../__tests__/__snapshots__/demo.test.js.snap | 345 ++++++++ components/table/demo/filter-in-tree.md | 2 - components/table/demo/filter-search.md | 99 +++ .../table/hooks/useFilter/FilterDropdown.tsx | 18 +- .../table/hooks/useFilter/FilterSearch.tsx | 4 +- components/table/index.en-US.md | 2 +- components/table/index.zh-CN.md | 2 +- components/table/interface.tsx | 1 + 10 files changed, 1330 insertions(+), 8 deletions(-) create mode 100644 components/table/demo/filter-search.md diff --git a/components/table/__tests__/Table.filter.test.js b/components/table/__tests__/Table.filter.test.js index 00a66669b3..132f8ffc66 100644 --- a/components/table/__tests__/Table.filter.test.js +++ b/components/table/__tests__/Table.filter.test.js @@ -1863,6 +1863,48 @@ describe('Table.filter', () => { expect(wrapper.find('li.ant-dropdown-menu-item').length).toBe(2); }); + it('should supports filterSearch has type of function', () => { + jest.useFakeTimers(); + jest.spyOn(console, 'error').mockImplementation(() => undefined); + const wrapper = mount( + createTable({ + columns: [ + { + ...column, + filters: [ + { + text: '123', + value: '123', + }, + { + text: 123456, + value: '456', + }, + { + text: 123, + value: '456', + }, + ], + filterSearch: (input, record) => record.value.indexOf(input) > -1, + }, + ], + }), + ); + wrapper.find('span.ant-dropdown-trigger').simulate('click', nativeEvent); + act(() => { + jest.runAllTimers(); + wrapper.update(); + }); + expect(wrapper.find(Menu).length).toBe(1); + expect(wrapper.find(Input).length).toBe(1); + expect(wrapper.find('li.ant-dropdown-menu-item').length).toBe(3); + wrapper + .find(Input) + .find('input') + .simulate('change', { target: { value: '456' } }); + expect(wrapper.find('li.ant-dropdown-menu-item').length).toBe(2); + }); + it('supports check all items', () => { jest.useFakeTimers(); jest.spyOn(console, 'error').mockImplementation(() => undefined); diff --git a/components/table/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/table/__tests__/__snapshots__/demo-extend.test.ts.snap index a82aac6149..55d91540cc 100644 --- a/components/table/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/table/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -7864,6 +7864,829 @@ exports[`renders ./components/table/demo/filter-in-tree.md extend context correc `; +exports[`renders ./components/table/demo/filter-search.md extend context correctly 1`] = ` +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Name + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ + +
+
+
+
+
+
+
+ + Age + + + + + + + + + + + +
+
+
+
+
+ +
+ +
+
+
+
+
+ + Address + + + + + + +
+
+
+ + + +
+
+
+ John Brown + + 32 + + New York No. 1 Lake Park +
+ Jim Green + + 42 + + London No. 1 Lake Park +
+ Joe Black + + 32 + + Sidney No. 1 Lake Park +
+ Jim Red + + 32 + + London No. 2 Lake Park +
+
+
+
+
    +
  • + +
  • +
  • + + 1 + +
  • +
  • + +
  • +
+
+
+
+`; + exports[`renders ./components/table/demo/fixed-columns.md extend context correctly 1`] = `
`; +exports[`renders ./components/table/demo/filter-search.md correctly 1`] = ` +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + Name + + + + + + +
+
+
+ + Age + + + + + + + + + + + +
+
+
+ + Address + + + + + + +
+
+ John Brown + + 32 + + New York No. 1 Lake Park +
+ Jim Green + + 42 + + London No. 1 Lake Park +
+ Joe Black + + 32 + + Sidney No. 1 Lake Park +
+ Jim Red + + 32 + + London No. 2 Lake Park +
+
+
+
+
    +
  • + +
  • +
  • + + 1 + +
  • +
  • + +
  • +
+
+
+
+`; + exports[`renders ./components/table/demo/fixed-columns.md correctly 1`] = `
`filterSearch` 用于开启筛选项的搜索。 - ## en-US You can use `filterMode` to change default filter interface, options: `menu`(default) and `tree`. diff --git a/components/table/demo/filter-search.md b/components/table/demo/filter-search.md new file mode 100644 index 0000000000..e144c554c3 --- /dev/null +++ b/components/table/demo/filter-search.md @@ -0,0 +1,99 @@ +--- +order: 6.2 +version: 4.19.0 +title: + en-US: Filter search + zh-CN: 自定义筛选的搜索 +--- + +## zh-CN + +`filterSearch` 用于开启筛选项的搜索,通过 `filterSearch:(input, record) => boolean` 设置自定义筛选方法 + +## en-US + +`filterSearch` is used to enable search of filter items, and you can set a custom filter method through `filterSearch:(input, record) => boolean`. + +```jsx +import { Table } from 'antd'; + +const columns = [ + { + title: 'Name', + dataIndex: 'name', + filters: [ + { + text: 'Joe', + value: 'Joe', + }, + { + text: 'Category 1', + value: 'Category 1', + }, + { + text: 'Category 2', + value: 'Category 2', + }, + ], + filterMode: 'tree', + filterSearch: true, + onFilter: (value, record) => record.address.startsWith(value), + width: '30%', + }, + { + title: 'Age', + dataIndex: 'age', + sorter: (a, b) => a.age - b.age, + }, + { + title: 'Address', + dataIndex: 'address', + filters: [ + { + text: London, + value: 'London', + }, + { + text: New York, + value: 'New York', + }, + ], + onFilter: (value, record) => record.address.startsWith(value), + filterSearch:(input, record) => record.value.indexOf(input) > -1, + width: '40%', + }, +]; + +const data = [ + { + key: '1', + name: 'John Brown', + age: 32, + address: 'New York No. 1 Lake Park', + }, + { + key: '2', + name: 'Jim Green', + age: 42, + address: 'London No. 1 Lake Park', + }, + { + key: '3', + name: 'Joe Black', + age: 32, + address: 'Sidney No. 1 Lake Park', + }, + { + key: '4', + name: 'Jim Red', + age: 32, + address: 'London No. 2 Lake Park', + }, +]; + +function onChange(pagination, filters, sorter, extra) { + console.log('params', pagination, filters, sorter, extra); +} + +ReactDOM.render(, mountNode); +``` diff --git a/components/table/hooks/useFilter/FilterDropdown.tsx b/components/table/hooks/useFilter/FilterDropdown.tsx index 21aae07c7e..ac0b5393d1 100644 --- a/components/table/hooks/useFilter/FilterDropdown.tsx +++ b/components/table/hooks/useFilter/FilterDropdown.tsx @@ -11,7 +11,14 @@ import type { CheckboxChangeEvent } from '../../../checkbox'; import Radio from '../../../radio'; import Dropdown from '../../../dropdown'; import Empty from '../../../empty'; -import { ColumnType, ColumnFilterItem, Key, TableLocale, GetPopupContainer } from '../../interface'; +import { + ColumnType, + ColumnFilterItem, + Key, + TableLocale, + GetPopupContainer, + FilterSearchType, +} from '../../interface'; import FilterDropdownMenuWrapper from './FilterWrapper'; import FilterSearch from './FilterSearch'; import { FilterState, flattenKeys } from '.'; @@ -40,12 +47,14 @@ function renderFilterItems({ filteredKeys, filterMultiple, searchValue, + filterSearch, }: { filters: ColumnFilterItem[]; prefixCls: string; filteredKeys: Key[]; filterMultiple: boolean; searchValue: string; + filterSearch: FilterSearchType; }) { return filters.map((filter, index) => { const key = String(filter.value); @@ -63,6 +72,7 @@ function renderFilterItems({ filteredKeys, filterMultiple, searchValue, + filterSearch, })} ); @@ -77,6 +87,9 @@ function renderFilterItems({ ); if (searchValue.trim()) { + if (typeof filterSearch === 'function') { + return filterSearch(searchValue, filter) ? item : undefined; + } return searchValueMatched(searchValue, filter.text) ? item : undefined; } return item; @@ -91,7 +104,7 @@ export interface FilterDropdownProps { filterState?: FilterState; filterMultiple: boolean; filterMode?: 'menu' | 'tree'; - filterSearch?: boolean; + filterSearch?: FilterSearchType; columnKey: Key; children: React.ReactNode; triggerFilter: (filterState: FilterState) => void; @@ -366,6 +379,7 @@ function FilterDropdown(props: FilterDropdownProps) { > {renderFilterItems({ filters: column.filters || [], + filterSearch, prefixCls, filteredKeys: getFilteredKeysSync(), filterMultiple, diff --git a/components/table/hooks/useFilter/FilterSearch.tsx b/components/table/hooks/useFilter/FilterSearch.tsx index ebd39a0ccc..fb1dacdc4e 100644 --- a/components/table/hooks/useFilter/FilterSearch.tsx +++ b/components/table/hooks/useFilter/FilterSearch.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; import SearchOutlined from '@ant-design/icons/SearchOutlined'; import Input from '../../../input'; -import { TableLocale } from '../../interface'; +import { TableLocale, FilterSearchType } from '../../interface'; interface FilterSearchProps { value: string; onChange: (e: React.ChangeEvent) => void; - filterSearch: Boolean; + filterSearch: FilterSearchType; tablePrefixCls: string; locale: TableLocale; } diff --git a/components/table/index.en-US.md b/components/table/index.en-US.md index 197004f72a..c19fce6262 100644 --- a/components/table/index.en-US.md +++ b/components/table/index.en-US.md @@ -130,7 +130,7 @@ One of the Table `columns` prop for describing the table's columns, Column has t | filterIcon | Customized filter icon | ReactNode \| (filtered: boolean) => ReactNode | - | | | filterMultiple | Whether multiple filters can be selected | boolean | true | | | filterMode | To specify the filter interface | 'menu' \| 'tree' | 'menu' | 4.17.0 | -| filterSearch | Whether to be searchable for filter menu | Boolean | false | 4.17.0 | +| filterSearch | Whether to be searchable for filter menu | boolean \| function(input, record):boolean | false | boolean:4.17.0 function:4.19.0 | | filters | Filter menu config | object\[] | - | | | fixed | (IE not support) Set column to be fixed: `true`(same as left) `'left'` `'right'` | boolean \| string | false | | | key | Unique key of this column, you can ignore this prop if you've set a unique `dataIndex` | string | - | | diff --git a/components/table/index.zh-CN.md b/components/table/index.zh-CN.md index cf7ee91007..6db807b71f 100644 --- a/components/table/index.zh-CN.md +++ b/components/table/index.zh-CN.md @@ -137,7 +137,7 @@ const columns = [ | filterIcon | 自定义 filter 图标。 | ReactNode \| (filtered: boolean) => ReactNode | false | | | filterMultiple | 是否多选 | boolean | true | | | filterMode | 指定筛选菜单的用户界面 | 'menu' \| 'tree' | 'menu' | 4.17.0 | -| filterSearch | 筛选菜单项是否可搜索 | Boolean | false | 4.17.0 | +| filterSearch | 筛选菜单项是否可搜索 | boolean \| function(input, record):boolean | false | boolean:4.17.0 function:4.19.0 | | filters | 表头的筛选菜单项 | object\[] | - | | | fixed | (IE 下无效)列是否固定,可选 true (等效于 left) `left` `right` | boolean \| string | false | | | key | React 需要的 key,如果已经设置了唯一的 `dataIndex`,可以忽略这个属性 | string | - | | diff --git a/components/table/interface.tsx b/components/table/interface.tsx index a88f85a426..d6477a18f2 100644 --- a/components/table/interface.tsx +++ b/components/table/interface.tsx @@ -73,6 +73,7 @@ export type ColumnTitle = export type FilterValue = (Key | boolean)[]; export type FilterKey = Key[] | null; +export type FilterSearchType = boolean | ((input: string, record: {}) => boolean); export interface FilterConfirmProps { closeDropdown: boolean; }