diff --git a/components/table/Column.tsx b/components/table/Column.tsx new file mode 100644 index 0000000000..6fd34100f0 --- /dev/null +++ b/components/table/Column.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import RcTable from 'rc-table'; + +export interface ColumnProps { + title?: React.ReactNode; + key?: string; + dataIndex?: string; + render?: (text: any, record: T, index: number) => React.ReactNode; + filters?: { text: string; value: string }[]; + onFilter?: (value: any, record: T) => boolean; + filterMultiple?: boolean; + filterDropdown?: React.ReactNode; + sorter?: boolean | ((a: any, b: any) => number); + colSpan?: number; + width?: string | number; + className?: string; + fixed?: boolean | ('left' | 'right'); + filteredValue?: any[]; + sortOrder?: boolean | ('ascend' | 'descend'); +} + +export default class Column extends (RcTable.Column as React.ComponentClass>) {} diff --git a/components/table/ColumnGroup.tsx b/components/table/ColumnGroup.tsx new file mode 100644 index 0000000000..2128d08695 --- /dev/null +++ b/components/table/ColumnGroup.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import RcTable from 'rc-table'; + +export interface ColumnGroupProps { + title?: React.ReactNode; +} + +export default class ColumnGroup extends (RcTable.ColumnGroup as React.ComponentClass) {} diff --git a/components/table/Table.tsx b/components/table/Table.tsx index ac56a6df39..c826b19abd 100755 --- a/components/table/Table.tsx +++ b/components/table/Table.tsx @@ -5,13 +5,15 @@ import Pagination, { PaginationProps } from '../pagination'; import Icon from '../icon'; import Spin from '../spin'; import classNames from 'classnames'; -import { flatArray, treeMap } from './util'; +import { flatArray, treeMap, normalizeColumns } from './util'; import assign from 'object-assign'; import splitObject from '../_util/splitObject'; import warning from '../_util/warning'; import createStore, { Store } from './createStore'; import SelectionBox from './SelectionBox'; import SelectionCheckboxAll from './SelectionCheckboxAll'; +import Column, { ColumnProps } from './Column'; +import ColumnGroup from './ColumnGroup'; function noop() { } @@ -44,24 +46,6 @@ export interface TableRowSelection { onSelectAll?: (selected: boolean, selectedRows: Object[], changeRows: Object[]) => any; } -export interface TableColumnConfig { - title?: React.ReactNode; - key?: string; - dataIndex?: string; - render?: (text: any, record: T, index: number) => React.ReactNode; - filters?: { text: string; value: string }[]; - onFilter?: (value: any, record: T) => boolean; - filterMultiple?: boolean; - filterDropdown?: React.ReactNode; - sorter?: boolean | ((a: any, b: any) => number); - colSpan?: number; - width?: string | number; - className?: string; - fixed?: boolean | ('left' | 'right'); - filteredValue?: any[]; - sortOrder?: boolean | ('ascend' | 'descend'); -} - export interface TableProps { prefixCls?: string; dropdownPrefixCls?: string; @@ -69,7 +53,7 @@ export interface TableProps { pagination?: PaginationProps | boolean; size?: 'default' | 'small'; dataSource?: T[]; - columns: TableColumnConfig[]; + columns?: ColumnProps[]; rowKey?: string | ((record: T, index: number) => string); rowClassName?: (record: T, index: number) => string; expandedRowRender?: any; @@ -100,9 +84,12 @@ export interface TableContext { } export default class Table extends React.Component, any> { + static Column = Column; + static ColumnGroup = ColumnGroup; + static propTypes = { dataSource: React.PropTypes.array, - columns: React.PropTypes.array.isRequired, + columns: React.PropTypes.array, prefixCls: React.PropTypes.string, useFixedHeader: React.PropTypes.bool, rowSelection: React.PropTypes.object, @@ -136,6 +123,7 @@ export default class Table extends React.Component, any> { context: TableContext; CheckboxPropsCache: Object; store: Store; + columns: ColumnProps[]; constructor(props) { super(props); @@ -149,6 +137,8 @@ export default class Table extends React.Component, any> { const pagination = props.pagination || {}; + this.columns = props.columns || normalizeColumns(props.children); + this.state = assign({}, this.getSortStateFromColumns(), { // 减少状态 filters: this.getFiltersFromColumns(), @@ -225,6 +215,8 @@ export default class Table extends React.Component, any> { )) { this.CheckboxPropsCache = {}; } + + this.columns = nextProps.columns || normalizeColumns(nextProps.children); } if (this.getSortOrderColumns(nextProps.columns).length > 0) { @@ -292,11 +284,11 @@ export default class Table extends React.Component, any> { } getSortOrderColumns(columns?) { - return (columns || this.props.columns || []).filter(column => 'sortOrder' in column); + return (columns || this.columns || []).filter(column => 'sortOrder' in column); } getFilteredValueColumns(columns?) { - return (columns || this.props.columns || []).filter(column => column.filteredValue); + return (columns || this.columns || []).filter(column => column.filteredValue); } getFiltersFromColumns(columns?) { @@ -376,7 +368,7 @@ export default class Table extends React.Component, any> { [this.getColumnKey(column)]: nextFilters, }); // Remove filters not in current columns - const currentColumnKeys = props.columns.map(c => this.getColumnKey(c)); + const currentColumnKeys = this.columns.map(c => this.getColumnKey(c)); Object.keys(filters).forEach((columnKey) => { if (currentColumnKeys.indexOf(columnKey) < 0) { delete filters[columnKey]; @@ -571,7 +563,7 @@ export default class Table extends React.Component, any> { renderRowSelection() { const { prefixCls, rowSelection } = this.props; - const columns = this.props.columns.concat(); + const columns = this.columns.concat(); if (rowSelection) { const data = this.getFlatCurrentPageData().filter((item) => { if (rowSelection.getCheckboxProps) { @@ -579,7 +571,7 @@ export default class Table extends React.Component, any> { } return true; }); - const selectionColumn: TableColumnConfig = { + const selectionColumn: ColumnProps = { key: 'selection-column', render: this.renderSelectionBox(rowSelection.type), className: `${prefixCls}-selection-column`, @@ -743,7 +735,7 @@ export default class Table extends React.Component, any> { } findColumn(myKey) { - return this.props.columns.filter(c => this.getColumnKey(c) === myKey)[0]; + return this.columns.filter(c => this.getColumnKey(c) === myKey)[0]; } getCurrentPageData() { diff --git a/components/table/demo/bordered.md b/components/table/demo/bordered.md index bea509f200..f62973ee56 100644 --- a/components/table/demo/bordered.md +++ b/components/table/demo/bordered.md @@ -1,5 +1,5 @@ --- -order: 10 +order: 11 title: en-US: border, title and footer zh-CN: 带边框 diff --git a/components/table/demo/colspan-rowspan.md b/components/table/demo/colspan-rowspan.md index 7fca9d3d0f..8d1d81826a 100644 --- a/components/table/demo/colspan-rowspan.md +++ b/components/table/demo/colspan-rowspan.md @@ -1,5 +1,5 @@ --- -order: 13 +order: 14 title: en-US: colSpan and rowSpan zh-CN: 表格行/列合并 diff --git a/components/table/demo/dynamic-settings.md b/components/table/demo/dynamic-settings.md index bec6d6dd05..f151428e3b 100644 --- a/components/table/demo/dynamic-settings.md +++ b/components/table/demo/dynamic-settings.md @@ -1,5 +1,5 @@ --- -order: 21 +order: 22 title: en-US: Dynamic Settings zh-CN: 动态控制表格属性 diff --git a/components/table/demo/expand-children.md b/components/table/demo/expand-children.md index ac8380944d..206b9fb68c 100644 --- a/components/table/demo/expand-children.md +++ b/components/table/demo/expand-children.md @@ -1,5 +1,5 @@ --- -order: 15 +order: 16 title: en-US: Tree data zh-CN: 树形数据展示 diff --git a/components/table/demo/expand.md b/components/table/demo/expand.md index abdd9a834f..020d3dbf6b 100644 --- a/components/table/demo/expand.md +++ b/components/table/demo/expand.md @@ -1,5 +1,5 @@ --- -order: 12 +order: 13 title: en-US: Expandable Row zh-CN: 可展开 diff --git a/components/table/demo/fixed-columns-header.md b/components/table/demo/fixed-columns-header.md index 3c7766e66c..3d99ef7244 100644 --- a/components/table/demo/fixed-columns-header.md +++ b/components/table/demo/fixed-columns-header.md @@ -1,5 +1,5 @@ --- -order: 18 +order: 19 title: en-US: Fixed Columns and Header zh-CN: 固定头和列 diff --git a/components/table/demo/fixed-columns.md b/components/table/demo/fixed-columns.md index eee2fe8fa9..1f8b3ed854 100644 --- a/components/table/demo/fixed-columns.md +++ b/components/table/demo/fixed-columns.md @@ -1,5 +1,5 @@ --- -order: 17 +order: 18 title: en-US: Fixed Columns zh-CN: 固定列 diff --git a/components/table/demo/fixed-header.md b/components/table/demo/fixed-header.md index 61179f7202..5b02f7c617 100644 --- a/components/table/demo/fixed-header.md +++ b/components/table/demo/fixed-header.md @@ -1,5 +1,5 @@ --- -order: 16 +order: 17 title: en-US: Fixed Header zh-CN: 固定表头 diff --git a/components/table/demo/grouping-columns.md b/components/table/demo/grouping-columns.md index d93c405c86..27849c94ca 100644 --- a/components/table/demo/grouping-columns.md +++ b/components/table/demo/grouping-columns.md @@ -1,5 +1,5 @@ --- -order: 20 +order: 21 title: en-US: Grouping table head zh-CN: 表头分组 diff --git a/components/table/demo/head.md b/components/table/demo/head.md index 4425f77f12..00d76afb02 100644 --- a/components/table/demo/head.md +++ b/components/table/demo/head.md @@ -1,5 +1,5 @@ --- -order: 6 +order: 7 title: en-US: Filter and sorter zh-CN: 筛选和排序 diff --git a/components/table/demo/jsx.md b/components/table/demo/jsx.md new file mode 100644 index 0000000000..aa433c4e23 --- /dev/null +++ b/components/table/demo/jsx.md @@ -0,0 +1,82 @@ +--- +order: 1 +title: + en-US: JSX style API + zh-CN: JSX 风格的 API +--- + +## zh-CN + +使用 JSX 风格的 API(2.5.0 以后引入) + +## en-US + +Using JSX style API (introduced in 2.5.0) + +````jsx +import { Table, Icon } from 'antd'; + +const { Column, ColumnGroup } = Table; + +const data = [{ + key: '1', + firstName: 'John', + lastName: 'Brown', + age: 32, + address: 'New York No. 1 Lake Park', +}, { + key: '2', + firstName: 'Jim', + lastName: 'Green', + age: 42, + address: 'London No. 1 Lake Park', +}, { + key: '3', + firstName: 'Joe', + lastName: 'Black', + age: 32, + address: 'Sidney No. 1 Lake Park', +}]; + +ReactDOM.render( + + + + + + + + ( + + Action 一 {record.name} + + Delete + + + More actions + + + )} + /> +
+, mountNode); +```` diff --git a/components/table/demo/nopagination.md b/components/table/demo/nopagination.md index 23e54f7e25..1cc88d8ea8 100644 --- a/components/table/demo/nopagination.md +++ b/components/table/demo/nopagination.md @@ -1,5 +1,5 @@ --- -order: 8 +order: 9 title: en-US: No pagination zh-CN: 不显示分页 diff --git a/components/table/demo/paging.md b/components/table/demo/paging.md index 37847a9d2b..0ff6ef4f3f 100644 --- a/components/table/demo/paging.md +++ b/components/table/demo/paging.md @@ -1,5 +1,5 @@ --- -order: 5 +order: 6 title: en-US: pagination zh-CN: 分页 diff --git a/components/table/demo/reset-filter.md b/components/table/demo/reset-filter.md index f9494e7c9f..04e11ce1dd 100644 --- a/components/table/demo/reset-filter.md +++ b/components/table/demo/reset-filter.md @@ -1,5 +1,5 @@ --- -order: 6 +order: 7 title: en-US: Reset filters and sorters zh-CN: 可控的筛选和排序 diff --git a/components/table/demo/row-selection-and-operation.md b/components/table/demo/row-selection-and-operation.md index 1d821e8326..9bb40d93c1 100644 --- a/components/table/demo/row-selection-and-operation.md +++ b/components/table/demo/row-selection-and-operation.md @@ -1,5 +1,5 @@ --- -order: 2 +order: 3 title: en-US: Selection and operation zh-CN: 选择和操作 diff --git a/components/table/demo/row-selection-props.md b/components/table/demo/row-selection-props.md index 613539e8d4..7b4e50ccd8 100644 --- a/components/table/demo/row-selection-props.md +++ b/components/table/demo/row-selection-props.md @@ -1,5 +1,5 @@ --- -order: 3 +order: 4 title: en-US: Checkbox props zh-CN: 选择框属性 diff --git a/components/table/demo/row-selection.md b/components/table/demo/row-selection.md index 7639677055..cd3b2f76c0 100644 --- a/components/table/demo/row-selection.md +++ b/components/table/demo/row-selection.md @@ -1,5 +1,5 @@ --- -order: 1 +order: 2 title: en-US: selection zh-CN: 可选择 diff --git a/components/table/demo/size.md b/components/table/demo/size.md index ec3bb8a586..44bd495347 100644 --- a/components/table/demo/size.md +++ b/components/table/demo/size.md @@ -1,5 +1,5 @@ --- -order: 9 +order: 10 title: en-US: size zh-CN: 紧凑型 diff --git a/components/table/index.en-US.md b/components/table/index.en-US.md index ccb0918ed9..d13e03cfb6 100644 --- a/components/table/index.en-US.md +++ b/components/table/index.en-US.md @@ -78,7 +78,7 @@ const columns = [{ ### Column -One of Property `columns` for describing column. +One of Property `columns` for descriping column, Column has the same API. | Property | Description | Type | Default | |---------------|--------------------------|-----------------|--------------| @@ -100,6 +100,12 @@ One of Property `columns` for describing column. | fixed | set column to be fixed: `true`(same as left) `'left'` `'right'` | Boolean or String | false | | sortOrder | controlled sorted value: `'ascend'` `'descend'` `false` | Boolean or String | - | +### ColumnGroup + +| Property | Description | Type | Default | +|---------------|--------------------------|-----------------|--------------| +| title | title of the column group | String or React.Element | - | + ### rowSelection Properties for selection. diff --git a/components/table/index.zh-CN.md b/components/table/index.zh-CN.md index 650f2f378e..91fd107f9d 100644 --- a/components/table/index.zh-CN.md +++ b/components/table/index.zh-CN.md @@ -79,7 +79,7 @@ const columns = [{ ### Column -列描述数据对象,是 columns 中的一项。 +列描述数据对象,是 columns 中的一项,Column 使用相同的 API。 | 参数 | 说明 | 类型 | 默认值 | |-----------|----------------------------|-----------------|---------| @@ -101,6 +101,12 @@ const columns = [{ | fixed | 列是否固定,可选 `true`(等效于 left) `'left'` `'right'` | Boolean or String | false | | sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 `'ascend'` `'descend'` `false` | Boolean or String | - | +### ColumnGroup + +| 参数 | 说明 | 类型 | 默认值 | +|-----------|----------------------------|-----------------|---------| +| title | 列头显示文字 | String or React.Element | - | + ### rowSelection 选择功能的配置。 diff --git a/components/table/util.tsx b/components/table/util.tsx index 6c7b56e9e4..ebd1abdb1a 100644 --- a/components/table/util.tsx +++ b/components/table/util.tsx @@ -1,4 +1,8 @@ +import React from 'react'; import assign from 'object-assign'; +import Column from './Column'; +import ColumnGroup from './ColumnGroup'; + export function flatArray(data: Object[] = [], childrenName = 'children') { const result: Object[] = []; const loop = (array) => { @@ -24,3 +28,25 @@ export function treeMap(tree: Object[], mapper: Function, childrenName = 'childr return assign({}, mapper(node, index), extra); }); } + +export function normalizeColumns(elements) { + const columns: any[] = []; + React.Children.forEach(elements, (element: React.ReactElement) => { + if (!isColumnElement(element)) { + return; + } + const column = assign({}, element.props); + if (element.key) { + column.key = element.key; + } + if (element.type as any === ColumnGroup) { + column.children = normalizeColumns(column.children); + } + columns.push(column); + }); + return columns; +} + +function isColumnElement(element) { + return element && (element.type === Column || element.type === ColumnGroup); +} diff --git a/package.json b/package.json index b1aac70ca2..4313b0235a 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "rc-slider": "~5.3.0", "rc-steps": "~2.2.0", "rc-switch": "~1.4.2", - "rc-table": "~5.0.0", + "rc-table": "~5.2.0", "rc-tabs": "~7.0.5", "rc-time-picker": "~2.2.1", "rc-tooltip": "~3.4.2", diff --git a/tests/table/Table.test.js b/tests/table/Table.test.js index 9748d31af8..ff2efb16af 100644 --- a/tests/table/Table.test.js +++ b/tests/table/Table.test.js @@ -2,6 +2,10 @@ import React from 'react'; import createStore from '../../components/table/createStore'; import Table from '../../components/table'; import TestUtils from 'react-addons-test-utils'; +import { render } from 'enzyme'; +import { renderToJson } from 'enzyme-to-json'; + +const { Column, ColumnGroup } = Table; describe('Table', () => { describe('row selection', () => { @@ -88,4 +92,44 @@ describe('Table', () => { expect(checkboxes[2].disabled).toBe(true); }); }); + + describe('JSX style API', () => { + it('renders correctly', () => { + const data = [{ + key: '1', + firstName: 'John', + lastName: 'Brown', + age: 32, + }, { + key: '2', + firstName: 'Jim', + lastName: 'Green', + age: 42, + }]; + + const wrapper = render( + + + + + + +
+ ); + + expect(renderToJson(wrapper)).toMatchSnapshot(); + }); + }); }) diff --git a/tests/table/__snapshots__/Table.test.js.snap b/tests/table/__snapshots__/Table.test.js.snap new file mode 100644 index 0000000000..75e3471c0b --- /dev/null +++ b/tests/table/__snapshots__/Table.test.js.snap @@ -0,0 +1,105 @@ +exports[`Table JSX style API renders correctly 1`] = ` +
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Name + + + + Age + +
+ + First Name + + + + Last Name + +
+ + John + + Brown + + 32 +
+ + Jim + + Green + + 42 +
+
+
+
+
+
+
+
+
+`;