From 5395a287a8d658f672d9a8b60debc4da1ba18ab4 Mon Sep 17 00:00:00 2001 From: MrHeer Date: Sun, 8 Sep 2019 09:25:05 +0800 Subject: [PATCH] :sparkles: Flipping table to automatically scroll to the top :ok_hand: apply it in handleFilter and toggleSortOrder :ok_hand: ref instead of findDOMNode :white_check_mark: update test for scroll to first row close #18623 --- components/table/Table.tsx | 23 +++++++++++++++---- .../table/__tests__/Table.pagination.test.js | 10 ++++++++ components/table/index.en-US.md | 2 +- components/table/index.zh-CN.md | 4 ++-- components/table/interface.tsx | 6 ++++- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/components/table/Table.tsx b/components/table/Table.tsx index c648fd7e99be..e16cad038d72 100755 --- a/components/table/Table.tsx +++ b/components/table/Table.tsx @@ -1,6 +1,5 @@ /* eslint-disable prefer-spread */ import * as React from 'react'; -import * as ReactDOM from 'react-dom'; import omit from 'omit.js'; import RcTable, { INTERNAL_COL_DEFINE } from 'rc-table'; import * as PropTypes from 'prop-types'; @@ -14,6 +13,7 @@ import Column from './Column'; import ColumnGroup from './ColumnGroup'; import createBodyRow from './createBodyRow'; import { flatArray, treeMap, flatFilter, normalizeColumns } from './util'; +import scrollTo from '../_util/scrollTo'; import { TableProps, TableSize, @@ -136,8 +136,11 @@ export default class Table extends React.Component, TableState< row: React.ComponentType; + rcTable: React.RefObject; + constructor(props: TableProps) { super(props); + this.rcTable = React.createRef(); const { expandedRowRender, columns = [] } = props; @@ -498,11 +501,21 @@ export default class Table extends React.Component, TableState< generatePopupContainerFunc = (getPopupContainer: TableProps['getPopupContainer']) => { const { scroll } = this.props; + const table = this.rcTable.current; if (getPopupContainer) { return getPopupContainer; } // Use undefined to let rc component use default logic. - return scroll ? () => ReactDOM.findDOMNode(this) as HTMLElement : undefined; + return scroll && table ? () => table.tableNode : undefined; + }; + + scrollToFirstRow = () => { + const { scroll } = this.props; + if (scroll && scroll.scrollToFirstRowOnChange !== false) { + scrollTo(0, { + getContainer: () => this.rcTable.current.bodyTable, + }); + } }; handleFilter = (column: ColumnProps, nextFilters: string[]) => { @@ -556,6 +569,7 @@ export default class Table extends React.Component, TableState< } this.setState(newState, () => { + this.scrollToFirstRow(); this.store.setState({ selectionDirty: false, }); @@ -747,7 +761,7 @@ export default class Table extends React.Component, TableState< current: this.state.pagination.current, }; } - this.setState(newState); + this.setState(newState, () => this.scrollToFirstRow()); this.store.setState({ selectionDirty: false, @@ -823,7 +837,7 @@ export default class Table extends React.Component, TableState< // Controlled if (this.getSortOrderColumns().length === 0) { - this.setState(newState); + this.setState(newState, () => this.scrollToFirstRow()); } const { onChange } = this.props; @@ -1258,6 +1272,7 @@ export default class Table extends React.Component, TableState< return ( { expect(renderedNames(wrapper)).toEqual(['Jack']); }); + // TODO + it('should scroll to first row when page change', () => { + const wrapper = mount(createTable({ scroll: { y: 20 } })); + + wrapper + .find('Pager') + .last() + .simulate('click'); + }); + it('fires change event', () => { const handleChange = jest.fn(); const handlePaginationChange = jest.fn(); diff --git a/components/table/index.en-US.md b/components/table/index.en-US.md index d61f3a0ae499..8b4da94147e2 100644 --- a/components/table/index.en-US.md +++ b/components/table/index.en-US.md @@ -79,7 +79,7 @@ const columns = [ | rowClassName | Row's className | Function(record, index):string | - | | | rowKey | Row's unique key, could be a string or function that returns a string | string\|Function(record):string | `key` | | | rowSelection | Row selection [config](#rowSelection) | object | null | | -| scroll | Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area, could be number, percent value, `true` and ['max-content'](https://developer.mozilla.org/en-US/docs/Web/CSS/width) | { x: number \| true, y: number } | - | | +| scroll | Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area, could be number, percent value, `true` and ['max-content'](https://developer.mozilla.org/en-US/docs/Web/CSS/width) | { x: number \| true, y: number, scrollToFirstRowOnChange: boolean } | - | | | showHeader | Whether to show table header | boolean | `true` | | | size | Size of table | `default` \| `middle` \| `small` | `default` | | | title | Table title renderer | Function(currentPageData) | | | diff --git a/components/table/index.zh-CN.md b/components/table/index.zh-CN.md index 3da83344ad1d..d34840e7216d 100644 --- a/components/table/index.zh-CN.md +++ b/components/table/index.zh-CN.md @@ -84,7 +84,7 @@ const columns = [ | rowClassName | 表格行的类名 | Function(record, index):string | - | | | rowKey | 表格行 key 的取值,可以是字符串或一个函数 | string\|Function(record):string | 'key' | | | rowSelection | 表格行是否可选择,[配置项](#rowSelection) | object | null | | -| scroll | 设置横向或纵向滚动,也可用于指定滚动区域的宽和高,可以设置为像素值,百分比,`true` 和 ['max-content'](https://developer.mozilla.org/zh-CN/docs/Web/CSS/width#max-content) | { x: number \| true, y: number } | - | | +| scroll | 设置横向或纵向滚动,也可用于指定滚动区域的宽和高,可以设置为像素值,百分比,`true` 和 ['max-content'](https://developer.mozilla.org/zh-CN/docs/Web/CSS/width#max-content) | { x: number \| true, y: number, scrollToFirstRowOnChange: boolean } | - | | | showHeader | 是否显示表头 | boolean | true | | | size | 表格大小 | default \| middle \| small | default | | | title | 表格标题 | Function(currentPageData) | | | @@ -143,7 +143,7 @@ const columns = [ | sorter | 排序函数,本地排序使用一个函数(参考 [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 的 compareFunction),需要服务端排序可设为 true | Function\|boolean | - | | | sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 `'ascend'` `'descend'` `false` | boolean\|string | - | | | sortDirections | 支持的排序方式,取值为 `'ascend'` `'descend'` | Array | `['ascend', 'descend']` | 3.15.2 | -| title | 列头显示文字(函数用法 `3.10.0` 后支持) | ReactNode\|({ sortOrder, filters }) => ReactNode | - | | +| title | 列头显示文字(函数用法 `3.10.0` 后支持) | ReactNode\|({ sortOrder, filters }) => ReactNode | - | | | width | 列宽度([指定了也不生效?](https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241)) | string\|number | - | | | onCell | 设置单元格属性 | Function(record, rowIndex) | - | | | onFilter | 本地模式下,确定筛选的运行函数 | Function | - | | diff --git a/components/table/interface.tsx b/components/table/interface.tsx index 678760141fb8..9f9f9c358ce1 100644 --- a/components/table/interface.tsx +++ b/components/table/interface.tsx @@ -187,7 +187,11 @@ export interface TableProps { showHeader?: boolean; footer?: (currentPageData: T[]) => React.ReactNode; title?: (currentPageData: T[]) => React.ReactNode; - scroll?: { x?: boolean | number | string; y?: boolean | number | string }; + scroll?: { + x?: boolean | number | string; + y?: boolean | number | string; + scrollToFirstRowOnChange?: boolean; + }; childrenColumnName?: string; bodyStyle?: React.CSSProperties; className?: string;