From d96c122d155ef5aa6091974ade7f9894234e9a5a Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Tue, 15 Nov 2016 19:13:06 +0800 Subject: [PATCH] Implement Table.Column and Table.ColumnGroup --- examples/jsx.html | 0 examples/jsx.js | 49 ++++++++++++++++++++++++++++++++++ src/Column.jsx | 21 +++++++++++++++ src/ColumnGroup.jsx | 7 +++++ src/ColumnManager.js | 33 ++++++++++++++++++++--- src/Table.jsx | 9 ++++--- src/index.js | 9 ++++++- tests/ColumnManager.spec.js | 52 +++++++++++++++++++++++++++++++++++++ 8 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 examples/jsx.html create mode 100644 examples/jsx.js create mode 100644 src/Column.jsx create mode 100644 src/ColumnGroup.jsx diff --git a/examples/jsx.html b/examples/jsx.html new file mode 100644 index 000000000..e69de29bb diff --git a/examples/jsx.js b/examples/jsx.js new file mode 100644 index 000000000..353876faf --- /dev/null +++ b/examples/jsx.js @@ -0,0 +1,49 @@ +/* eslint-disable no-console,func-names,react/no-multi-comp */ +const React = require('react'); +const ReactDOM = require('react-dom'); +const Table = require('rc-table'); +require('rc-table/assets/index.less'); + +const { ColumnGroup, Column } = Table; + +const data = [ + { a: '123', key: '1' }, + { a: 'cdd', b: 'edd', key: '2' }, + { a: '1333', c: 'eee', d: 2, key: '3' }, +]; + +ReactDOM.render( +
+

JSX table

+ + + + + + + Operations} + /> +
+
, + document.getElementById('__react-content') +); diff --git a/src/Column.jsx b/src/Column.jsx new file mode 100644 index 000000000..8a167ea2d --- /dev/null +++ b/src/Column.jsx @@ -0,0 +1,21 @@ +import { Component, PropTypes } from 'react'; + +export default class Column extends Component { + static propTypes = { + className: PropTypes.string, + colSpan: PropTypes.number, + title: PropTypes.node, + dataIndex: PropTypes.string, + width: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), + fixed: PropTypes.oneOf([ + true, + 'left', + 'right', + ]), + render: PropTypes.func, + onCellClick: PropTypes.func, + } +} diff --git a/src/ColumnGroup.jsx b/src/ColumnGroup.jsx new file mode 100644 index 000000000..6ea54a065 --- /dev/null +++ b/src/ColumnGroup.jsx @@ -0,0 +1,7 @@ +import { Component, PropTypes } from 'react'; + +export default class ColumnGroup extends Component { + static propTypes = { + title: PropTypes.node, + } +} diff --git a/src/ColumnManager.js b/src/ColumnManager.js index 2ab8d96b6..821f12f37 100644 --- a/src/ColumnManager.js +++ b/src/ColumnManager.js @@ -1,8 +1,12 @@ +import React from 'react'; +import Column from './Column'; +import ColumnGroup from './ColumnGroup'; + export default class ColumnManager { _cached = {} - constructor(columns) { - this.columns = columns; + constructor(columns, elements) { + this.columns = columns || this.normalize(elements); } static includesCustomRender(columns) { @@ -109,8 +113,29 @@ export default class ColumnManager { }); } - reset(columns) { - this.columns = columns; + normalize(elements) { + const columns = []; + React.Children.forEach(elements, element => { + if (!this.isColumnElement(element)) return; + const clonedElement = React.cloneElement(element); + const column = { ...clonedElement.props }; + if (clonedElement.key) { + column.key = clonedElement.key; + } + if (element.type === ColumnGroup) { + column.children = this.normalize(column.children); + } + columns.push(column); + }); + return columns; + } + + isColumnElement(element) { + return element && (element.type === Column || element.type === ColumnGroup); + } + + reset(columns, elements) { + this.columns = columns || this.normalize(elements); this._cached = {}; } diff --git a/src/Table.jsx b/src/Table.jsx index df1d2246f..fb5e14dd5 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -36,6 +36,7 @@ const Table = React.createClass({ scroll: PropTypes.object, rowRef: PropTypes.func, getBodyWrapper: PropTypes.func, + children: PropTypes.node, }, getDefaultProps() { @@ -43,7 +44,6 @@ const Table = React.createClass({ data: [], useFixedHeader: false, expandIconAsCell: false, - columns: [], defaultExpandAllRows: false, defaultExpandedRowKeys: [], rowKey: 'key', @@ -71,8 +71,7 @@ const Table = React.createClass({ const props = this.props; let expandedRowKeys = []; let rows = [...props.data]; - - this.columnManager = new ColumnManager(props.columns); + this.columnManager = new ColumnManager(props.columns, props.children); this.store = createStore({ currentHoverKey: null }); if (props.defaultExpandAllRows) { @@ -118,8 +117,10 @@ const Table = React.createClass({ expandedRowKeys: nextProps.expandedRowKeys, }); } - if (nextProps.columns !== this.props.columns) { + if (nextProps.columns && nextProps.columns !== this.props.columns) { this.columnManager.reset(nextProps.columns); + } else if (nextProps.children !== this.props.children) { + this.columnManager.reset(null, nextProps.children); } }, diff --git a/src/index.js b/src/index.js index df36b6e6c..8175c76db 100644 --- a/src/index.js +++ b/src/index.js @@ -1 +1,8 @@ -module.exports = require('./Table'); +const Table = require('./Table'); +const Column = require('./Column'); +const ColumnGroup = require('./ColumnGroup'); + +Table.Column = Column; +Table.ColumnGroup = ColumnGroup; + +module.exports = Table; diff --git a/tests/ColumnManager.spec.js b/tests/ColumnManager.spec.js index 673a69d33..095a4501f 100644 --- a/tests/ColumnManager.spec.js +++ b/tests/ColumnManager.spec.js @@ -1,6 +1,9 @@ /* eslint-disable no-console,func-names,react/no-multi-comp,indent */ +const React = require('react'); const expect = require('expect.js'); const ColumnManager = require('../src/ColumnManager'); +const Column = require('../src/Column'); +const ColumnGroup = require('../src/ColumnGroup'); describe('ColumnManager', () => { describe('includesCustomRender', () => { @@ -94,4 +97,53 @@ describe('ColumnManager', () => { ]); }); }); + + describe('normalize', () => { + it('normalize React elements to columns', () => { + const elements = [ + + + + , + , + ]; + + const columnManager = new ColumnManager(null, elements); + + expect(columnManager.columns).to.eql([ + { + title: 'a', + children: [ + { + title: 'b', + dataIndex: 'b', + key: 'b', + }, + { + title: 'c', + dataIndex: 'c', + key: 'c', + }, + ], + }, + { + title: 'd', + dataIndex: 'd', + key: 'd', + }, + ]); + }); + }); });