feat: add select none functionality (#28580)

This commit is contained in:
不吃猫的鱼 2020-12-29 10:38:43 +08:00 committed by GitHub
parent 9b0bed7a7f
commit 5119d2a9e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 68 additions and 4 deletions

View File

@ -24,6 +24,7 @@ const localeValues: Locale = {
emptyText: 'No data', emptyText: 'No data',
selectAll: 'Select current page', selectAll: 'Select current page',
selectInvert: 'Invert current page', selectInvert: 'Invert current page',
selectNone: 'Clear all data',
selectionAll: 'Select all data', selectionAll: 'Select all data',
sortTitle: 'Sort', sortTitle: 'Sort',
expand: 'Expand row', expand: 'Expand row',

View File

@ -24,6 +24,7 @@ const localeValues: Locale = {
filterEmptyText: '无筛选项', filterEmptyText: '无筛选项',
selectAll: '全选当页', selectAll: '全选当页',
selectInvert: '反选当页', selectInvert: '反选当页',
selectNone: '清空所有',
selectionAll: '全选所有', selectionAll: '全选所有',
sortTitle: '排序', sortTitle: '排序',
expand: '展开行', expand: '展开行',

View File

@ -23,6 +23,7 @@ const localeValues: Locale = {
filterEmptyText: '無篩選項', filterEmptyText: '無篩選項',
selectAll: '全部選取', selectAll: '全部選取',
selectInvert: '反向選取', selectInvert: '反向選取',
selectNone: '清空所有',
selectionAll: '全選所有', selectionAll: '全選所有',
sortTitle: '排序', sortTitle: '排序',
expand: '展開行', expand: '展開行',

View File

@ -23,6 +23,7 @@ const localeValues: Locale = {
filterEmptyText: '無篩選項', filterEmptyText: '無篩選項',
selectAll: '全部選取', selectAll: '全部選取',
selectInvert: '反向選取', selectInvert: '反向選取',
selectNone: '清空所有',
selectionAll: '全選所有', selectionAll: '全選所有',
sortTitle: '排序', sortTitle: '排序',
expand: '展開行', expand: '展開行',

View File

@ -26,7 +26,11 @@ import {
TableLocale, TableLocale,
TableAction, TableAction,
} from './interface'; } from './interface';
import useSelection, { SELECTION_ALL, SELECTION_INVERT } from './hooks/useSelection'; import useSelection, {
SELECTION_ALL,
SELECTION_INVERT,
SELECTION_NONE,
} from './hooks/useSelection';
import useSorter, { getSortData, SortState } from './hooks/useSorter'; import useSorter, { getSortData, SortState } from './hooks/useSorter';
import useFilter, { getFilterData, FilterState } from './hooks/useFilter'; import useFilter, { getFilterData, FilterState } from './hooks/useFilter';
import useTitleColumns from './hooks/useTitleColumns'; import useTitleColumns from './hooks/useTitleColumns';
@ -509,6 +513,7 @@ Table.defaultProps = {
Table.SELECTION_ALL = SELECTION_ALL; Table.SELECTION_ALL = SELECTION_ALL;
Table.SELECTION_INVERT = SELECTION_INVERT; Table.SELECTION_INVERT = SELECTION_INVERT;
Table.SELECTION_NONE = SELECTION_NONE;
Table.Column = Column; Table.Column = Column;
Table.ColumnGroup = ColumnGroup; Table.ColumnGroup = ColumnGroup;
Table.Summary = Summary; Table.Summary = Summary;

View File

@ -294,11 +294,28 @@ describe('Table.rowSelection', () => {
checkboxes.at(1).simulate('change', { target: { checked: true } }); checkboxes.at(1).simulate('change', { target: { checked: true } });
const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent()); const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent());
dropdownWrapper.find('.ant-dropdown-menu-item').last().simulate('click'); dropdownWrapper.find('.ant-dropdown-menu-item').at(1).simulate('click');
expect(handleSelectInvert).toHaveBeenCalledWith([1, 2, 3]); expect(handleSelectInvert).toHaveBeenCalledWith([1, 2, 3]);
}); });
it('fires selectNone event', () => {
const handleSelectNone = jest.fn();
const rowSelection = {
onSelectNone: handleSelectNone,
selections: true,
};
const wrapper = mount(createTable({ rowSelection }));
const checkboxes = wrapper.find('input');
checkboxes.at(1).simulate('change', { target: { checked: true } });
const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent());
dropdownWrapper.find('.ant-dropdown-menu-item').last().simulate('click');
expect(handleSelectNone).toHaveBeenCalled();
});
it('fires selection event', () => { it('fires selection event', () => {
const handleSelectOdd = jest.fn(); const handleSelectOdd = jest.fn();
const handleSelectEven = jest.fn(); const handleSelectEven = jest.fn();

View File

@ -984,6 +984,12 @@ exports[`Table.rowSelection render with default selection correctly 1`] = `
> >
Invert current page Invert current page
</li> </li>
<li
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
role="menuitem"
>
Clear all data
</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -1093,6 +1099,12 @@ exports[`Table.rowSelection should support getPopupContainer 1`] = `
> >
Invert current page Invert current page
</li> </li>
<li
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
role="menuitem"
>
Clear all data
</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -1420,6 +1432,12 @@ exports[`Table.rowSelection should support getPopupContainer from ConfigProvider
> >
Invert current page Invert current page
</li> </li>
<li
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
role="menuitem"
>
Clear all data
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -59,6 +59,7 @@ class App extends React.Component {
selections: [ selections: [
Table.SELECTION_ALL, Table.SELECTION_ALL,
Table.SELECTION_INVERT, Table.SELECTION_INVERT,
Table.SELECTION_NONE,
{ {
key: 'odd', key: 'odd',
text: 'Select Odd Row', text: 'Select Odd Row',

View File

@ -28,6 +28,7 @@ import {
// TODO: warning if use ajax!!! // TODO: warning if use ajax!!!
export const SELECTION_ALL = 'SELECT_ALL' as const; export const SELECTION_ALL = 'SELECT_ALL' as const;
export const SELECTION_INVERT = 'SELECT_INVERT' as const; export const SELECTION_INVERT = 'SELECT_INVERT' as const;
export const SELECTION_NONE = 'SELECT_NONE' as const;
function getFixedType<RecordType>(column: ColumnsType<RecordType>[number]): FixedType | undefined { function getFixedType<RecordType>(column: ColumnsType<RecordType>[number]): FixedType | undefined {
return column && column.fixed; return column && column.fixed;
@ -49,7 +50,8 @@ interface UseSelectionConfig<RecordType> {
export type INTERNAL_SELECTION_ITEM = export type INTERNAL_SELECTION_ITEM =
| SelectionItem | SelectionItem
| typeof SELECTION_ALL | typeof SELECTION_ALL
| typeof SELECTION_INVERT; | typeof SELECTION_INVERT
| typeof SELECTION_NONE;
function flattenData<RecordType>( function flattenData<RecordType>(
data: RecordType[] | undefined, data: RecordType[] | undefined,
@ -82,6 +84,7 @@ export default function useSelection<RecordType>(
onSelect, onSelect,
onSelectAll, onSelectAll,
onSelectInvert, onSelectInvert,
onSelectNone,
onSelectMultiple, onSelectMultiple,
columnWidth: selectionColWidth, columnWidth: selectionColWidth,
type: selectionType, type: selectionType,
@ -255,7 +258,7 @@ export default function useSelection<RecordType>(
} }
const selectionList: INTERNAL_SELECTION_ITEM[] = const selectionList: INTERNAL_SELECTION_ITEM[] =
selections === true ? [SELECTION_ALL, SELECTION_INVERT] : selections; selections === true ? [SELECTION_ALL, SELECTION_INVERT, SELECTION_NONE] : selections;
return selectionList.map((selection: INTERNAL_SELECTION_ITEM) => { return selectionList.map((selection: INTERNAL_SELECTION_ITEM) => {
if (selection === SELECTION_ALL) { if (selection === SELECTION_ALL) {
@ -296,6 +299,18 @@ export default function useSelection<RecordType>(
}, },
}; };
} }
if (selection === SELECTION_NONE) {
return {
key: 'none',
text: tableLocale.selectNone,
onSelect() {
setSelectedKeys([]);
if (onSelectNone) {
onSelectNone();
}
},
};
}
return selection as SelectionItem; return selection as SelectionItem;
}); });
}, [selections, derivedSelectedKeySet, pageData, getRowKey, onSelectInvert, setSelectedKeys]); }, [selections, derivedSelectedKeySet, pageData, getRowKey, onSelectInvert, setSelectedKeys]);

View File

@ -203,6 +203,7 @@ Properties for row selection.
| onSelect | Callback executed when select/deselect one row | function(record, selected, selectedRows, nativeEvent) | - | | | onSelect | Callback executed when select/deselect one row | function(record, selected, selectedRows, nativeEvent) | - | |
| onSelectAll | Callback executed when select/deselect all rows | function(selected, selectedRows, changeRows) | - | | | onSelectAll | Callback executed when select/deselect all rows | function(selected, selectedRows, changeRows) | - | |
| onSelectInvert | Callback executed when row selection is inverted | function(selectedRowKeys) | - | | | onSelectInvert | Callback executed when row selection is inverted | function(selectedRowKeys) | - | |
| onSelectNone | Callback executed when row selection is cleared | function() | - | |
### scroll ### scroll

View File

@ -210,6 +210,7 @@ const columns = [
| onSelect | 用户手动选择/取消选择某行的回调 | function(record, selected, selectedRows, nativeEvent) | - | | | onSelect | 用户手动选择/取消选择某行的回调 | function(record, selected, selectedRows, nativeEvent) | - | |
| onSelectAll | 用户手动选择/取消选择所有行的回调 | function(selected, selectedRows, changeRows) | - | | | onSelectAll | 用户手动选择/取消选择所有行的回调 | function(selected, selectedRows, changeRows) | - | |
| onSelectInvert | 用户手动选择反选的回调 | function(selectedRowKeys) | - | | | onSelectInvert | 用户手动选择反选的回调 | function(selectedRowKeys) | - | |
| onSelectNone | 用户清空选择的回调 | function() | - | |
### scroll ### scroll

View File

@ -29,6 +29,7 @@ export interface TableLocale {
filterEmptyText?: React.ReactNode; filterEmptyText?: React.ReactNode;
emptyText?: React.ReactNode | (() => React.ReactNode); emptyText?: React.ReactNode | (() => React.ReactNode);
selectAll?: React.ReactNode; selectAll?: React.ReactNode;
selectNone?: React.ReactNode;
selectInvert?: React.ReactNode; selectInvert?: React.ReactNode;
selectionAll?: React.ReactNode; selectionAll?: React.ReactNode;
sortTitle?: string; sortTitle?: string;
@ -143,6 +144,7 @@ export interface TableRowSelection<T> {
onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => void; onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => void;
/** @deprecated This function is meaningless and should use `onChange` instead */ /** @deprecated This function is meaningless and should use `onChange` instead */
onSelectInvert?: (selectedRowKeys: Key[]) => void; onSelectInvert?: (selectedRowKeys: Key[]) => void;
onSelectNone?: () => void;
selections?: INTERNAL_SELECTION_ITEM[] | boolean; selections?: INTERNAL_SELECTION_ITEM[] | boolean;
hideSelectAll?: boolean; hideSelectAll?: boolean;
fixed?: boolean; fixed?: boolean;