Table: add prop sortDirections for table and column (#13773)

* Table: add prop `sortMethods`

with `sortMethods` user can change table sort methods and its order

* Table: `sortMethods` can be set on column prop

* rename `sortMethods` to `sortDirections`
This commit is contained in:
Harlan 2018-12-22 18:16:02 +08:00 committed by 偏右
parent 22daf9e6af
commit 6b6ec278cc
5 changed files with 92 additions and 34 deletions

View File

@ -87,6 +87,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
onChange: PropTypes.func,
locale: PropTypes.object,
dropdownPrefixCls: PropTypes.string,
sortDirections: PropTypes.array,
};
static defaultProps = {
@ -100,6 +101,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
locale: {},
rowKey: 'key',
showHeader: true,
sortDirections: ['ascend', 'descend'],
};
CheckboxPropsCache: {
@ -382,18 +384,18 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
if (!column.sorter) {
return;
}
const sortDirections = column.sortDirections || this.props.sortDirections;
const { sortOrder, sortColumn } = this.state;
// 只同时允许一列进行排序,否则会导致排序顺序的逻辑问题
let newSortOrder: 'descend' | 'ascend' | undefined;
// 切换另一列时,丢弃 sortOrder 的状态
const oldSortOrder = this.isSameColumn(sortColumn, column) ? sortOrder : undefined;
// 切换排序状态,按照降序/升序/不排序的顺序
if (!oldSortOrder) {
newSortOrder = 'ascend';
} else if (oldSortOrder === 'ascend') {
newSortOrder = 'descend';
if (this.isSameColumn(sortColumn, column) && sortOrder !== undefined) {
// 按照sortDirections的内容依次切换排序状态
const methodIndex = sortDirections.indexOf(sortOrder) + 1;
newSortOrder =
methodIndex === sortDirections.length ? undefined : sortDirections[methodIndex];
} else {
newSortOrder = undefined;
newSortOrder = sortDirections[0];
}
const newState = {
@ -832,20 +834,30 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
);
}
if (column.sorter) {
const sortDirections = column.sortDirections || this.props.sortDirections;
const isAscend = isSortColumn && sortOrder === 'ascend';
const isDescend = isSortColumn && sortOrder === 'descend';
const ascend = sortDirections.indexOf('ascend') !== -1 && (
<Icon
className={`${prefixCls}-column-sorter-up ${isAscend ? 'on' : 'off'}`}
type="caret-up"
theme="filled"
/>
);
const descend = sortDirections.indexOf('descend') !== -1 && (
<Icon
className={`${prefixCls}-column-sorter-down ${isDescend ? 'on' : 'off'}`}
type="caret-down"
theme="filled"
/>
);
sortButton = (
<div className={`${prefixCls}-column-sorter`} key="sorter">
<Icon
className={`${prefixCls}-column-sorter-up ${isAscend ? 'on' : 'off'}`}
type="caret-up"
theme="filled"
/>
<Icon
className={`${prefixCls}-column-sorter-down ${isDescend ? 'on' : 'off'}`}
type="caret-down"
theme="filled"
/>
{ascend}
{descend}
</div>
);

View File

@ -532,4 +532,59 @@ describe('Table.sorter', () => {
.getDOMNode().className,
).toContain(' off');
});
it('should first sort by descend, then ascend, then cancel sort', () => {
const wrapper = mount(
createTable({
sortDirections: ['descend', 'ascend'],
}),
);
// descend
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
// ascend
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
// cancel sort
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
});
it('should first sort by descend, then cancel sort', () => {
const wrapper = mount(
createTable({
sortDirections: ['descend'],
}),
);
// descend
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
// cancel sort
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
});
it('should first sort by descend, then cancel sort. (column prop)', () => {
const wrapper = mount(
createTable(
{},
{
sortDirections: ['descend'],
},
),
);
// descend
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
// cancel sort
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']);
});
});

View File

@ -9172,23 +9172,6 @@ exports[`renders ./components/table/demo/head.md correctly 1`] = `
<div
class="ant-table-column-sorter"
>
<i
class="anticon anticon-caret-up ant-table-column-sorter-up off"
>
<svg
aria-hidden="true"
class=""
data-icon="caret-up"
fill="currentColor"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"
/>
</svg>
</i>
<i
class="anticon anticon-caret-down ant-table-column-sorter-down off"
>

View File

@ -11,6 +11,8 @@ title:
对某一列数据进行排序,通过指定列的 `sorter` 函数即可启动排序按钮。`sorter: function(rowA, rowB) { ... }` rowA、rowB 为比较的两个行数据。
`sortDirections: ['ascend' | 'descend']`改变每列可用的排序方式切换排序时按数组内容依次切换设置在table props上时对所有列生效。
使用 `defaultSortOrder` 属性,设置列的默认排序顺序。
## en-US
@ -19,6 +21,8 @@ Use `filters` to generate filter menu in columns, `onFilter` to determine filter
Use `sorter` to make a column sortable. `sorter` can be a function of the type `function(a, b) { ... }` for sorting data locally.
`sortDirections: ['ascend' | 'descend']` defines available sort methods for each columns, effective for all columns when set on table props.
Uses `defaultSortOrder` to make a column sorted by default.
If a `sortOrder` or `defaultSortOrder` is specified with the value `ascend` or `descend`, you can access this value from within the function passed to the `sorter` as explained above. Such a function can take the form: `function(a, b, sortOrder) { ... }`.
@ -50,6 +54,7 @@ const columns = [{
// here is that finding the name started with `value`
onFilter: (value, record) => record.name.indexOf(value) === 0,
sorter: (a, b) => a.name.length - b.name.length,
sortDirections: ['descend'],
}, {
title: 'Age',
dataIndex: 'age',
@ -68,6 +73,7 @@ const columns = [{
filterMultiple: false,
onFilter: (value, record) => record.address.indexOf(value) === 0,
sorter: (a, b) => a.address.length - b.address.length,
sortDirections: ['descend', 'ascend'],
}];
const data = [{

View File

@ -41,6 +41,7 @@ export interface ColumnProps<T> {
onCellClick?: (record: T, event: any) => void;
onCell?: (record: T, rowIndex: number) => any;
onHeaderCell?: (props: ColumnProps<T>) => any;
sortDirections?: SortOrder[];
}
export interface AdditionalCellProps {
@ -162,6 +163,7 @@ export interface TableProps<T> {
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
sortDirections: SortOrder[];
}
export interface TableStateFilters {