mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 02:59:58 +08:00
feat(table): Add defaultFilteredValues to table columns (#20088)
This commit is contained in:
parent
05c2f92b69
commit
3ef0a402b5
@ -20,10 +20,7 @@ describe('Table.filter', () => {
|
||||
{
|
||||
text: 'Title',
|
||||
value: 'title',
|
||||
children: [
|
||||
{ text: 'Designer', value: 'designer' },
|
||||
{ text: 'Coder', value: 'coder' },
|
||||
],
|
||||
children: [{ text: 'Designer', value: 'designer' }, { text: 'Coder', value: 'coder' }],
|
||||
},
|
||||
],
|
||||
onFilter: filterFn,
|
||||
@ -310,6 +307,58 @@ describe('Table.filter', () => {
|
||||
expect(wrapper.find('tbody tr').length).toBe(4);
|
||||
});
|
||||
|
||||
it('can read defaults from defaultFilteredValue', () => {
|
||||
const wrapper = mount(
|
||||
createTable({
|
||||
columns: [
|
||||
{
|
||||
...column,
|
||||
defaultFilteredValue: ['Lucy'],
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
expect(wrapper.find('tbody tr').length).toBe(1);
|
||||
expect(wrapper.find('tbody tr').text()).toBe('Lucy');
|
||||
|
||||
// Should properly ignore further defaultFilteredValue changes
|
||||
wrapper.setProps({
|
||||
columns: [
|
||||
{
|
||||
...column,
|
||||
defaultFilteredValue: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(wrapper.find('tbody tr').length).toBe(1);
|
||||
expect(wrapper.find('tbody tr').text()).toBe('Lucy');
|
||||
|
||||
// Should properly be overidden by non-null filteredValue
|
||||
wrapper.setProps({
|
||||
columns: [
|
||||
{
|
||||
...column,
|
||||
defaultFilteredValue: ['Lucy'],
|
||||
filteredValue: ['Tom'],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(wrapper.find('tbody tr').length).toBe(1);
|
||||
expect(wrapper.find('tbody tr').text()).toBe('Tom');
|
||||
|
||||
// Should properly be overidden by a null filteredValue
|
||||
wrapper.setProps({
|
||||
columns: [
|
||||
{
|
||||
...column,
|
||||
defaultFilteredValue: ['Lucy'],
|
||||
filteredValue: null,
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(wrapper.find('tbody tr').length).toBe(4);
|
||||
});
|
||||
|
||||
it('fires change event', () => {
|
||||
const handleChange = jest.fn();
|
||||
const wrapper = mount(createTable({ onChange: handleChange }));
|
||||
@ -418,10 +467,7 @@ describe('Table.filter', () => {
|
||||
// });
|
||||
|
||||
describe('should support value types', () => {
|
||||
[
|
||||
['Light', 93],
|
||||
['Bamboo', false],
|
||||
].forEach(([text, value]) => {
|
||||
[['Light', 93], ['Bamboo', false]].forEach(([text, value]) => {
|
||||
it(`${typeof value} type`, () => {
|
||||
const onFilter = jest.fn();
|
||||
const filters = [{ text, value }];
|
||||
@ -505,10 +551,7 @@ describe('Table.filter', () => {
|
||||
title="name"
|
||||
dataIndex="name"
|
||||
key="name"
|
||||
filters={[
|
||||
{ text: 'Jack', value: 'Jack' },
|
||||
{ text: 'Lucy', value: 'Lucy' },
|
||||
]}
|
||||
filters={[{ text: 'Jack', value: 'Jack' }, { text: 'Lucy', value: 'Lucy' }]}
|
||||
filteredValue={filters.name}
|
||||
onFilter={filterFn}
|
||||
/>
|
||||
@ -547,10 +590,7 @@ describe('Table.filter', () => {
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
filters: [
|
||||
{ text: 'Jack', value: 'Jack' },
|
||||
{ text: 'Lucy', value: 'Lucy' },
|
||||
],
|
||||
filters: [{ text: 'Jack', value: 'Jack' }, { text: 'Lucy', value: 'Lucy' }],
|
||||
onFilter: filterFn,
|
||||
filteredValue: ['Jack'],
|
||||
},
|
||||
@ -580,10 +620,7 @@ describe('Table.filter', () => {
|
||||
columns: [
|
||||
{
|
||||
...column,
|
||||
filters: [
|
||||
{ text: 'Jack', value: 'Jack' },
|
||||
{ text: 'Lucy', value: 'Lucy' },
|
||||
],
|
||||
filters: [{ text: 'Jack', value: 'Jack' }, { text: 'Lucy', value: 'Lucy' }],
|
||||
},
|
||||
],
|
||||
onChange: handleChange,
|
||||
|
@ -22,6 +22,7 @@ export interface FilterState<RecordType> {
|
||||
|
||||
function collectFilterStates<RecordType>(
|
||||
columns: ColumnsType<RecordType>,
|
||||
init: boolean,
|
||||
pos?: string,
|
||||
): FilterState<RecordType>[] {
|
||||
let filterStates: FilterState<RecordType>[] = [];
|
||||
@ -30,14 +31,24 @@ function collectFilterStates<RecordType>(
|
||||
const columnPos = getColumnPos(index, pos);
|
||||
|
||||
if ('children' in column) {
|
||||
filterStates = [...filterStates, ...collectFilterStates(column.children, columnPos)];
|
||||
filterStates = [...filterStates, ...collectFilterStates(column.children, init, columnPos)];
|
||||
} else if ('filters' in column || 'filterDropdown' in column) {
|
||||
// Controlled
|
||||
filterStates.push({
|
||||
column,
|
||||
key: getColumnKey(column, columnPos),
|
||||
filteredKeys: column.filteredValue,
|
||||
});
|
||||
if ('filteredValue' in column) {
|
||||
// Controlled
|
||||
filterStates.push({
|
||||
column,
|
||||
key: getColumnKey(column, columnPos),
|
||||
filteredKeys: column.filteredValue,
|
||||
});
|
||||
} else {
|
||||
// Uncontrolled
|
||||
filterStates.push({
|
||||
column,
|
||||
key: getColumnKey(column, columnPos),
|
||||
filteredKeys:
|
||||
init && column.defaultFilteredValue ? column.defaultFilteredValue! : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -172,11 +183,11 @@ function useFilter<RecordType>({
|
||||
const tableLocale = (locale.Table || {}) as TableLocale;
|
||||
|
||||
const [filterStates, setFilterStates] = React.useState<FilterState<RecordType>[]>(
|
||||
collectFilterStates(columns),
|
||||
collectFilterStates(columns, true),
|
||||
);
|
||||
|
||||
const mergedFilterStates = React.useMemo(() => {
|
||||
const collectedStates = collectFilterStates(columns);
|
||||
const collectedStates = collectFilterStates(columns, false);
|
||||
|
||||
// Return if not controlled
|
||||
if (collectedStates.every(({ filteredKeys }) => filteredKeys === undefined)) {
|
||||
|
@ -116,6 +116,7 @@ One of the Table `columns` prop for describing the table's columns, Column has t
|
||||
| className | className of this column | string | - |
|
||||
| colSpan | Span of this column's title | number | - |
|
||||
| dataIndex | Display field of the data record, support nest path by string array | string \| string\[] | - |
|
||||
| defaultFilteredValue | Default filtered values | string\[] | - | |
|
||||
| defaultSortOrder | Default order of sorted values | 'ascend' \| 'descend' | - |
|
||||
| filterDropdown | Customized filter overlay | React.ReactNode \| (props: [FilterDropdownProps](https://git.io/fjP5h)) => React.ReactNode | - |
|
||||
| filterDropdownVisible | Whether `filterDropdown` is visible | boolean | - |
|
||||
|
@ -121,6 +121,7 @@ const columns = [
|
||||
| className | 列样式类名 | string | - |
|
||||
| colSpan | 表头列合并,设置为 0 时,不渲染 | number | - |
|
||||
| dataIndex | 列数据在数据项中对应的路径,支持通过数组查询嵌套路径 | string \| string\[] | - |
|
||||
| defaultFilteredValue | 默认筛选值 | string\[] | - | |
|
||||
| defaultSortOrder | 默认排序顺序 | 'ascend' \| 'descend' | - |
|
||||
| filterDropdown | 可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 | React.ReactNode \| (props: [FilterDropdownProps](https://git.io/fjP5h)) => React.ReactNode | - |
|
||||
| filterDropdownVisible | 用于控制自定义筛选菜单是否可见 | boolean | - |
|
||||
|
@ -83,6 +83,7 @@ export interface ColumnType<RecordType> extends RcColumnType<RecordType> {
|
||||
filterDropdown?: React.ReactNode | ((props: FilterDropdownProps) => React.ReactNode);
|
||||
filterMultiple?: boolean;
|
||||
filteredValue?: Key[] | null;
|
||||
defaultFilteredValue?: Key[] | null;
|
||||
filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode);
|
||||
onFilter?: (value: any, record: RecordType) => boolean;
|
||||
filterDropdownVisible?: boolean;
|
||||
@ -95,8 +96,7 @@ export interface ColumnGroupType<RecordType> extends ColumnType<RecordType> {
|
||||
|
||||
export type ColumnsType<RecordType = unknown> = (
|
||||
| ColumnGroupType<RecordType>
|
||||
| ColumnType<RecordType>
|
||||
)[];
|
||||
| ColumnType<RecordType>)[];
|
||||
|
||||
export interface SelectionItem {
|
||||
key: string;
|
||||
|
Loading…
Reference in New Issue
Block a user