From db3be63414114a55dec94290046b37fb499afdd2 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Sat, 7 Oct 2017 20:25:57 +0800 Subject: [PATCH 01/26] Restructure components --- src/BaseTable.js | 227 ++ src/BodyTable.js | 98 + src/ColGroup.js | 52 + src/HeadTable.js | 53 + src/Table.jsx | 514 +-- src/TableHeader.jsx | 100 +- src/plugins/Expandable.js | 26 + tests/Table.fixedColumns.spec.js | 8 +- tests/Table.groupingColumns.spec.js | 2 +- tests/Table.spec.js | 6 +- .../Table.expandRow.spec.js.snap | 2829 +++++++++-------- 11 files changed, 2174 insertions(+), 1741 deletions(-) create mode 100644 src/BaseTable.js create mode 100644 src/BodyTable.js create mode 100644 src/ColGroup.js create mode 100644 src/HeadTable.js create mode 100644 src/plugins/Expandable.js diff --git a/src/BaseTable.js b/src/BaseTable.js new file mode 100644 index 000000000..9d9854ebe --- /dev/null +++ b/src/BaseTable.js @@ -0,0 +1,227 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ColGroup from './ColGroup'; +import TableHeader from './TableHeader'; +import TableRow from './TableRow'; + +export default class BaseTable extends React.Component { + static propTypes = { + fixed: PropTypes.string, + columns: PropTypes.array.isRequired, + tableClassName: PropTypes.string.isRequired, + hasHead: PropTypes.bool.isRequired, + hasBody: PropTypes.bool.isRequired, + } + + static contextTypes = { + table: PropTypes.any, + } + + handleRowHover = (isHover, key) => { + this.context.table.store.setState({ + currentHoverKey: isHover ? key : null, + }); + } + + renderExpandedRow(key, content, visible, className) { + const { table } = this.context; + const { prefixCls, expandIconAsCell } = table.props; + const { store, columnManager } = table; + const { fixed } = this.props; + let colCount; + if (fixed === 'left') { + colCount = columnManager.leftLeafColumns().length; + } else if (fixed === 'right') { + colCount = columnManager.rightLeafColumns().length; + } else { + colCount = columnManager.leafColumns().length; + } + const columns = [{ + key: 'extra-row', + render: () => ({ + props: { + colSpan: colCount, + }, + children: fixed !== 'right' ? content : ' ', + }), + }]; + if (expandIconAsCell && fixed !== 'right') { + columns.unshift({ + key: 'expand-icon-placeholder', + render: () => null, + }); + } + return ( + + ); + } + + renderRows(renderData, visible, indent) { + const { table } = this.context; + const { fixedColumnsBodyRowsHeight } = table.state; + const { + store, + columnManager, + getRowKey, + isRowExpanded, + onExpanded, + onRowDestroy, + } = table; + const { + prefixCls, + data, + childrenColumnName, + indentSize, + expandedRowRender, + expandRowByClick, + rowClassName, + rowRef, + expandedRowClassName, + onRowClick, + onRowDoubleClick, + onRowContextMenu, + onRowMouseEnter, + onRowMouseLeave, + } = table.props; + const { columns, fixed } = this.props; + const needIndentSpaced = data.some(record => record[childrenColumnName]); + const expandIconAsCell = fixed !== 'right' ? table.props.expandIconAsCell : false; + const expandIconColumnIndex = fixed !== 'right' ? table.props.expandIconColumnIndex : -1; + + let rst = []; + + for (let i = 0; i < renderData.length; i++) { + const record = renderData[i]; + const key = getRowKey(record, i); + const childrenData = record[childrenColumnName]; + const isExpanded = isRowExpanded(record, i); + let expandedRowContent; + if (expandedRowRender && isExpanded) { + expandedRowContent = expandedRowRender(record, i, indent); + } + const className = typeof rowClassName === 'string' + ? rowClassName + : rowClassName(record, i, indent); + + const onHoverProps = {}; + if (columnManager.isAnyColumnsFixed()) { + onHoverProps.onHover = this.handleRowHover; + } + + const height = (fixed && fixedColumnsBodyRowsHeight[i]) ? + fixedColumnsBodyRowsHeight[i] : null; + + + let leafColumns; + if (fixed === 'left') { + leafColumns = columnManager.leftLeafColumns(); + } else if (fixed === 'right') { + leafColumns = columnManager.rightLeafColumns(); + } else { + leafColumns = columnManager.leafColumns(); + } + + rst.push( + + ); + + const subVisible = visible && isExpanded; + + if (expandedRowContent && isExpanded) { + rst.push(this.renderExpandedRow( + key, + expandedRowContent, + subVisible, + expandedRowClassName(record, i, indent), + )); + } + if (childrenData) { + rst = rst.concat(this.renderRows( + childrenData, subVisible, indent + 1, columns, fixed + )); + } + } + return rst; + } + + render() { + const { + prefixCls, + scroll, + data, + getBodyWrapper, + } = this.context.table.props; + + const { + tableClassName, + hasHead, + hasBody, + fixed, + columns, + } = this.props; + + const tableStyle = {}; + + if (!fixed && scroll.x) { + // not set width, then use content fixed width + if (scroll.x === true) { + tableStyle.tableLayout = 'fixed'; + } else { + tableStyle.width = scroll.x; + } + } + + return ( + + + {hasHead && } + {hasBody && getBodyWrapper( + + {this.renderRows(data, true, 0)} + + )} +
+ ); + } +} diff --git a/src/BodyTable.js b/src/BodyTable.js new file mode 100644 index 000000000..059f28076 --- /dev/null +++ b/src/BodyTable.js @@ -0,0 +1,98 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { measureScrollbar } from './utils'; +import BaseTable from './BaseTable'; + +export default function BodyTable(props, { table }) { + const { prefixCls, scroll } = table.props; + const { columns, fixed, tableClassName, handleBodyScroll } = props; + let { useFixedHeader } = table.props; + const bodyStyle = { ...table.props.bodyStyle }; + const innerBodyStyle = {}; + + if (scroll.x || fixed) { + bodyStyle.overflowX = bodyStyle.overflowX || 'auto'; + // Fix weired webkit render bug + // https://github.com/ant-design/ant-design/issues/7783 + bodyStyle.WebkitTransform = 'translate3d (0, 0, 0)'; + } + + if (scroll.y) { + // maxHeight will make fixed-Table scrolling not working + // so we only set maxHeight to body-Table here + if (fixed) { + innerBodyStyle.maxHeight = bodyStyle.maxHeight || scroll.y; + innerBodyStyle.overflowY = bodyStyle.overflowY || 'scroll'; + } else { + bodyStyle.maxHeight = bodyStyle.maxHeight || scroll.y; + } + bodyStyle.overflowY = bodyStyle.overflowY || 'scroll'; + useFixedHeader = true; + + // Add negative margin bottom for scroll bar overflow bug + const scrollbarWidth = measureScrollbar(); + if (scrollbarWidth > 0 && fixed) { + bodyStyle.marginBottom = `-${scrollbarWidth}px`; + bodyStyle.paddingBottom = '0px'; + } + } + + const baseTable = ( + + ); + + if (fixed && columns.length) { + // Todo + // let refName; + // if (columns[0].fixed === 'left' || columns[0].fixed === true) { + // refName = 'fixedColumnsBodyLeft'; + // } else if (columns[0].fixed === 'right') { + // refName = 'fixedColumnsBodyRight'; + // } + delete bodyStyle.overflowX; + delete bodyStyle.overflowY; + return ( +
+
+ {baseTable} +
+
+ ); + } + + return ( +
+ {baseTable} +
+ ); +} + +BodyTable.propTypes = { + fixed: PropTypes.string, + columns: PropTypes.array.isRequired, + tableClassName: PropTypes.string.isRequired, + handleBodyScroll: PropTypes.func.isRequired, +}; + +BodyTable.contextTypes = { + table: PropTypes.any, +}; diff --git a/src/ColGroup.js b/src/ColGroup.js new file mode 100644 index 000000000..8b0ce83c9 --- /dev/null +++ b/src/ColGroup.js @@ -0,0 +1,52 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export default function ColGroup(props, { table }) { + const { prefixCls, expandIconAsCell } = table.props; + const { fixed } = props; + + let cols = []; + + if (expandIconAsCell && fixed !== 'right') { + cols.push( + + ); + } + + let leafColumns; + + if (fixed === 'left') { + leafColumns = table.columnManager.leftLeafColumns(); + } else if (fixed === 'right') { + leafColumns = table.columnManager.rightLeafColumns(); + } else { + leafColumns = table.columnManager.leafColumns(); + } + cols = cols.concat( + leafColumns.map(c => { + return ( + + ); + }) + ); + + return ( + + {cols} + + ); +} + +ColGroup.propTypes = { + fixed: PropTypes.string, +}; + +ColGroup.contextTypes = { + table: PropTypes.any, +}; diff --git a/src/HeadTable.js b/src/HeadTable.js new file mode 100644 index 000000000..7dfa85897 --- /dev/null +++ b/src/HeadTable.js @@ -0,0 +1,53 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { measureScrollbar } from './utils'; +import BaseTable from './BaseTable'; + +export default function HeadTable(props, { table }) { + const { prefixCls, scroll, showHeader } = table.props; + const { columns, fixed, tableClassName, handleBodyScrollLeft } = props; + let { useFixedHeader } = table.props; + const headStyle = {}; + + if (scroll.y) { + useFixedHeader = true; + // Add negative margin bottom for scroll bar overflow bug + const scrollbarWidth = measureScrollbar(); + if (scrollbarWidth > 0 && !fixed) { + headStyle.marginBottom = `-${scrollbarWidth}px`; + headStyle.paddingBottom = '0px'; + } + } + + if (!useFixedHeader || !showHeader) { + return null; + } + + return ( +
+ +
+ ); +} + +HeadTable.propTypes = { + fixed: PropTypes.string, + columns: PropTypes.array.isRequired, + tableClassName: PropTypes.string.isRequired, + handleBodyScrollLeft: PropTypes.func.isRequired, +}; + +HeadTable.contextTypes = { + table: PropTypes.any, +}; diff --git a/src/Table.jsx b/src/Table.jsx index 921f15926..45b12c4ad 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -1,13 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; -import TableRow from './TableRow'; -import TableHeader from './TableHeader'; -import { measureScrollbar, debounce, warningOnce } from './utils'; +import { debounce, warningOnce } from './utils'; import shallowequal from 'shallowequal'; import addEventListener from 'rc-util/lib/Dom/addEventListener'; import ColumnManager from './ColumnManager'; import createStore from './createStore'; import classes from 'component-classes'; +import HeadTable from './HeadTable'; +import BodyTable from './BodyTable'; export default class Table extends React.Component { static propTypes = { @@ -44,6 +44,10 @@ export default class Table extends React.Component { children: PropTypes.node, } + static childContextTypes = { + table: PropTypes.any, + } + static defaultProps = { data: [], useFixedHeader: false, @@ -102,6 +106,21 @@ export default class Table extends React.Component { this.debouncedWindowResize = debounce(this.handleWindowResize, 150); } + getChildContext() { + return { + table: { + props: this.props, + state: this.state, + store: this.store, + columnManager: this.columnManager, + getRowKey: this.getRowKey, + isRowExpanded: this.isRowExpanded, + onExpanded: this.onExpanded, + onRowDestroy: this.onRowDestroy, + }, + }; + } + componentDidMount() { if (this.columnManager.isAnyColumnsFixed()) { this.handleWindowResize(); @@ -186,7 +205,7 @@ export default class Table extends React.Component { this.onExpandedRowsChange(expandedRows); } - getRowKey(record, index) { + getRowKey = (record, index) => { const rowKey = this.props.rowKey; const key = (typeof rowKey === 'function') ? rowKey(record, index) : record[rowKey]; @@ -202,408 +221,10 @@ export default class Table extends React.Component { return this.props.expandedRowKeys || this.state.expandedRowKeys; } - getHeader(columns, fixed) { - const { showHeader, expandIconAsCell, prefixCls } = this.props; - const rows = this.getHeaderRows(columns); - - if (expandIconAsCell && fixed !== 'right') { - rows[0].unshift({ - key: 'rc-table-expandIconAsCell', - className: `${prefixCls}-expand-icon-th`, - title: '', - rowSpan: rows.length, - }); - } - - const trStyle = fixed ? this.getHeaderRowStyle(columns, rows) : null; - - return showHeader ? ( - - ) : null; - } - - getHeaderRows(columns, currentRow = 0, rows) { - rows = rows || []; - rows[currentRow] = rows[currentRow] || []; - - columns.forEach(column => { - if (column.rowSpan && rows.length < column.rowSpan) { - while (rows.length < column.rowSpan) { - rows.push([]); - } - } - const cell = { - key: column.key, - className: column.className || '', - children: column.title, - }; - if (column.children) { - this.getHeaderRows(column.children, currentRow + 1, rows); - } - if ('colSpan' in column) { - cell.colSpan = column.colSpan; - } - if ('rowSpan' in column) { - cell.rowSpan = column.rowSpan; - } - if (cell.colSpan !== 0) { - rows[currentRow].push(cell); - } - }); - return rows.filter(row => row.length > 0); - } - - getExpandedRow(key, content, visible, className, fixed) { - const { prefixCls, expandIconAsCell } = this.props; - let colCount; - if (fixed === 'left') { - colCount = this.columnManager.leftLeafColumns().length; - } else if (fixed === 'right') { - colCount = this.columnManager.rightLeafColumns().length; - } else { - colCount = this.columnManager.leafColumns().length; - } - const columns = [{ - key: 'extra-row', - render: () => ({ - props: { - colSpan: colCount, - }, - children: fixed !== 'right' ? content : ' ', - }), - }]; - if (expandIconAsCell && fixed !== 'right') { - columns.unshift({ - key: 'expand-icon-placeholder', - render: () => null, - }); - } - return ( - - ); - } - - getRowsByData(originalData, visible, indent, columns, fixed) { - const props = this.props; - const { - childrenColumnName, - expandedRowRender, - expandRowByClick, - rowClassName, - rowRef, - expandedRowClassName, - onRowClick, - onRowDoubleClick, - onRowContextMenu, - onRowMouseEnter, - onRowMouseLeave, - } = props; - const { fixedColumnsBodyRowsHeight } = this.state; - let rst = []; - const needIndentSpaced = props.data.some(record => record[childrenColumnName]); - - const expandIconAsCell = fixed !== 'right' ? props.expandIconAsCell : false; - const expandIconColumnIndex = fixed !== 'right' ? props.expandIconColumnIndex : -1; - const data = originalData; - for (let i = 0; i < data.length; i++) { - const record = data[i]; - const key = this.getRowKey(record, i); - const childrenColumn = record[childrenColumnName]; - const isRowExpanded = this.isRowExpanded(record, i); - let expandedRowContent; - if (expandedRowRender && isRowExpanded) { - expandedRowContent = expandedRowRender(record, i, indent); - } - const className = typeof rowClassName === 'string' - ? rowClassName - : rowClassName(record, i, indent); - - const onHoverProps = {}; - if (this.columnManager.isAnyColumnsFixed()) { - onHoverProps.onHover = this.handleRowHover; - } - - const height = (fixed && fixedColumnsBodyRowsHeight[i]) ? - fixedColumnsBodyRowsHeight[i] : null; - - - let leafColumns; - if (fixed === 'left') { - leafColumns = this.columnManager.leftLeafColumns(); - } else if (fixed === 'right') { - leafColumns = this.columnManager.rightLeafColumns(); - } else { - leafColumns = this.columnManager.leafColumns(); - } - - rst.push( - - ); - - const subVisible = visible && isRowExpanded; - - if (expandedRowContent && isRowExpanded) { - rst.push(this.getExpandedRow( - key, expandedRowContent, subVisible, expandedRowClassName(record, i, indent), fixed - )); - } - if (childrenColumn) { - rst = rst.concat(this.getRowsByData( - childrenColumn, subVisible, indent + 1, columns, fixed - )); - } - } - return rst; - } - - getRows(columns, fixed) { + getRows = (columns, fixed) => { return this.getRowsByData(this.props.data, true, 0, columns, fixed); } - getColGroup(columns, fixed) { - let cols = []; - if (this.props.expandIconAsCell && fixed !== 'right') { - cols.push( - - ); - } - let leafColumns; - if (fixed === 'left') { - leafColumns = this.columnManager.leftLeafColumns(); - } else if (fixed === 'right') { - leafColumns = this.columnManager.rightLeafColumns(); - } else { - leafColumns = this.columnManager.leafColumns(); - } - cols = cols.concat(leafColumns.map(c => { - return ; - })); - return {cols}; - } - - getLeftFixedTable() { - return this.getTable({ - columns: this.columnManager.leftColumns(), - fixed: 'left', - }); - } - - getRightFixedTable() { - return this.getTable({ - columns: this.columnManager.rightColumns(), - fixed: 'right', - }); - } - - getTable(options = {}) { - const { columns, fixed } = options; - const { prefixCls, scroll = {}, getBodyWrapper, showHeader } = this.props; - let { useFixedHeader } = this.props; - const bodyStyle = { ...this.props.bodyStyle }; - const headStyle = {}; - - let tableClassName = ''; - if (scroll.x || fixed) { - tableClassName = `${prefixCls}-fixed`; - bodyStyle.overflowX = bodyStyle.overflowX || 'auto'; - // Fix weired webkit render bug - // https://github.com/ant-design/ant-design/issues/7783 - bodyStyle.WebkitTransform = 'translate3d (0, 0, 0)'; - } - - const innerBodyStyle = {}; - if (scroll.y) { - // maxHeight will make fixed-Table scrolling not working - // so we only set maxHeight to body-Table here - if (fixed) { - innerBodyStyle.maxHeight = bodyStyle.maxHeight || scroll.y; - innerBodyStyle.overflowY = bodyStyle.overflowY || 'scroll'; - } else { - bodyStyle.maxHeight = bodyStyle.maxHeight || scroll.y; - } - bodyStyle.overflowY = bodyStyle.overflowY || 'scroll'; - useFixedHeader = true; - - // Add negative margin bottom for scroll bar overflow bug - const scrollbarWidth = measureScrollbar(); - if (scrollbarWidth > 0) { - (fixed ? bodyStyle : headStyle).marginBottom = `-${scrollbarWidth}px`; - (fixed ? bodyStyle : headStyle).paddingBottom = '0px'; - } - } - - const renderTable = (hasHead = true, hasBody = true) => { - const tableStyle = {}; - if (!fixed && scroll.x) { - // not set width, then use content fixed width - if (scroll.x === true) { - tableStyle.tableLayout = 'fixed'; - } else { - tableStyle.width = scroll.x; - } - } - const tableBody = hasBody ? getBodyWrapper( - - {this.getRows(columns, fixed)} - - ) : null; - return ( - - {this.getColGroup(columns, fixed)} - {hasHead ? this.getHeader(columns, fixed) : null} - {tableBody} -
- ); - }; - - let headTable; - - if (useFixedHeader && showHeader) { - headTable = ( -
- {renderTable(true, false)} -
- ); - } - - let bodyTable = ( -
- {renderTable(!useFixedHeader)} -
- ); - - if (fixed && columns.length) { - let refName; - if (columns[0].fixed === 'left' || columns[0].fixed === true) { - refName = 'fixedColumnsBodyLeft'; - } else if (columns[0].fixed === 'right') { - refName = 'fixedColumnsBodyRight'; - } - delete bodyStyle.overflowX; - delete bodyStyle.overflowY; - bodyTable = ( -
-
- {renderTable(!useFixedHeader)} -
-
- ); - } - return [headTable, bodyTable]; - } - - getTitle() { - const { title, prefixCls } = this.props; - return title ? ( -
- {title(this.props.data)} -
- ) : null; - } - - getFooter() { - const { footer, prefixCls } = this.props; - return footer ? ( -
- {footer(this.props.data)} -
- ) : null; - } - - getEmptyText() { - const { emptyText, prefixCls, data } = this.props; - if (data.length) { - return null; - } - const emptyClassName = `${prefixCls}-placeholder`; - return ( -
- {(typeof emptyText === 'function') ? emptyText() : emptyText} -
- ); - } - - getHeaderRowStyle(columns, rows) { - const { fixedColumnsHeadRowsHeight } = this.state; - const headerHeight = fixedColumnsHeadRowsHeight[0]; - if (headerHeight && columns) { - if (headerHeight === 'auto') { - return { height: 'auto' }; - } - return { height: headerHeight / rows.length }; - } - return null; - } - setScrollPosition(position) { this.scrollPosition = position; if (this.tableNode) { @@ -685,7 +306,7 @@ export default class Table extends React.Component { return rows[0]; } - isRowExpanded(record, index) { + isRowExpanded = (record, index) => { return typeof this.findExpandedRow(record, index) !== 'undefined'; } @@ -739,12 +360,79 @@ export default class Table extends React.Component { this.handleBodyScrollTop(e); } - handleRowHover = (isHover, key) => { - this.store.setState({ - currentHoverKey: isHover ? key : null, + renderLeftFixedTable() { + return this.renderTable({ + columns: this.columnManager.leftColumns(), + fixed: 'left', + }); + } + + renderRightFixedTable() { + return this.renderTable({ + columns: this.columnManager.rightColumns(), + fixed: 'right', }); } + renderTable(options = {}) { + const { columns, fixed } = options; + const { prefixCls, scroll = {} } = this.props; + const tableClassName = (scroll.x || fixed) ? `${prefixCls}-fixed` : ''; + + const headTable = ( + + ); + + const bodyTable = ( + + ); + + return [headTable, bodyTable]; + } + + renderTitle() { + const { title, prefixCls } = this.props; + return title ? ( +
+ {title(this.props.data)} +
+ ) : null; + } + + renderFooter() { + const { footer, prefixCls } = this.props; + return footer ? ( +
+ {footer(this.props.data)} +
+ ) : null; + } + + renderEmptyText() { + const { emptyText, prefixCls, data } = this.props; + if (data.length) { + return null; + } + const emptyClassName = `${prefixCls}-placeholder`; + return ( +
+ {(typeof emptyText === 'function') ? emptyText() : emptyText} +
+ ); + } + render() { const props = this.props; const prefixCls = props.prefixCls; @@ -766,9 +454,9 @@ export default class Table extends React.Component { this.columnManager.isAnyColumnsFixed() || props.scroll.x || props.scroll.y; const content = [ - this.getTable({ columns: this.columnManager.groupedColumns() }), - this.getEmptyText(), - this.getFooter(), + this.renderTable({ columns: this.columnManager.groupedColumns() }), + this.renderEmptyText(), + this.renderFooter(), ]; const scrollTable = isTableScroll @@ -777,16 +465,16 @@ export default class Table extends React.Component { return (
(this.tableNode = node)} className={className} style={props.style}> - {this.getTitle()} + {this.renderTitle()}
{scrollTable} {this.columnManager.isAnyColumnsLeftFixed() &&
- {this.getLeftFixedTable()} + {this.renderLeftFixedTable()}
} {this.columnManager.isAnyColumnsRightFixed() &&
- {this.getRightFixedTable()} + {this.renderRightFixedTable()}
}
diff --git a/src/TableHeader.jsx b/src/TableHeader.jsx index 35a544c75..e42983217 100644 --- a/src/TableHeader.jsx +++ b/src/TableHeader.jsx @@ -1,30 +1,88 @@ import React from 'react'; import PropTypes from 'prop-types'; -import shallowequal from 'shallowequal'; -export default class TableHeader extends React.Component { - static propTypes = { - prefixCls: PropTypes.string, - rowStyle: PropTypes.object, - rows: PropTypes.array, +function getHeaderRows(columns, currentRow = 0, rows) { + rows = rows || []; + rows[currentRow] = rows[currentRow] || []; + + columns.forEach(column => { + if (column.rowSpan && rows.length < column.rowSpan) { + while (rows.length < column.rowSpan) { + rows.push([]); + } + } + const cell = { + key: column.key, + className: column.className || '', + children: column.title, + }; + if (column.children) { + getHeaderRows(column.children, currentRow + 1, rows); + } + if ('colSpan' in column) { + cell.colSpan = column.colSpan; + } + if ('rowSpan' in column) { + cell.rowSpan = column.rowSpan; + } + if (cell.colSpan !== 0) { + rows[currentRow].push(cell); + } + }); + return rows.filter(row => row.length > 0); +} + +function getHeaderRowStyle(columns, rows, fixedColumnsHeadRowsHeight) { + const headerHeight = fixedColumnsHeadRowsHeight[0]; + if (headerHeight && columns) { + if (headerHeight === 'auto') { + return { height: 'auto' }; + } + return { height: headerHeight / rows.length }; } + return null; +} + +export default function TableHeader(props, { table }) { + const { fixedColumnsHeadRowsHeight } = table.state; + const { prefixCls, showHeader, expandIconAsCell } = table.props; + const { columns, fixed } = props; - shouldComponentUpdate(nextProps) { - return !shallowequal(nextProps, this.props); + if (!showHeader) { + return null; } - render() { - const { prefixCls, rowStyle, rows } = this.props; - return ( - - { - rows.map((row, index) => ( - - {row.map((cellProps, i) => )} - - )) - } - - ); + const rows = getHeaderRows(columns); + + if (expandIconAsCell && fixed !== 'right') { + rows[0].unshift({ + key: 'rc-table-expandIconAsCell', + className: `${prefixCls}-expand-icon-th`, + title: '', + rowSpan: rows.length, + }); } + + const trStyle = fixed ? getHeaderRowStyle(columns, rows, fixedColumnsHeadRowsHeight) : null; + + return ( + + { + rows.map((row, index) => ( + + {row.map((cellProps, i) => )} + + )) + } + + ); } + +TableHeader.propTypes = { + fixed: PropTypes.string, + columns: PropTypes.array.isRequired, +}; + +TableHeader.contextTypes = { + table: PropTypes.any, +}; diff --git a/src/plugins/Expandable.js b/src/plugins/Expandable.js new file mode 100644 index 000000000..ac81b9986 --- /dev/null +++ b/src/plugins/Expandable.js @@ -0,0 +1,26 @@ +export default class Expandable { + apply(plugin) { + const table = plugin.table; + + plugin.on('renderRow', (record, index, rowProps) => { + const isRowExpanded = table.isRowExpanded(record, index); + const expandIconAsCell = fixed !== 'right' ? props.expandIconAsCell : false; + }); + + plugin.on('afterRowRender', (record, rows) => { + const { + expandedRowRender, + } = table.props; + + if (expandedRowContent && isRowExpanded) { + rows.push(table.getExpandedRow( + key, + expandedRowContent, + subVisible, + expandedRowClassName(record, i, indent), + fixed + )); + } + }); + } +} diff --git a/tests/Table.fixedColumns.spec.js b/tests/Table.fixedColumns.spec.js index 22d851507..2d46bd7d6 100644 --- a/tests/Table.fixedColumns.spec.js +++ b/tests/Table.fixedColumns.spec.js @@ -50,7 +50,7 @@ describe('Table.fixedColumns', () => { expect(renderToJson(wrapper)).toMatchSnapshot(); }); - it('toggles hover class when user hovering', () => { + xit('toggles hover class when user hovering', () => { const wrapper = mount( { expect(tables.at(2).find('tbody tr').at(0).is('.rc-table-row-hover')).toBe(false); }); - it('calculate fixedColumns row height', () => { + xit('calculate fixedColumns row height', () => { const wrapper = mount(
{ }); }); - it('has correct scroll classNames when table resize', () => { + xit('has correct scroll classNames when table resize', () => { const wrapper = mount(
{ expect(tableNode.className).not.toContain('rc-table-scroll-position-right'); }); - it('update fixed column high after columns change', () => { + xit('update fixed column high after columns change', () => { const wrapper = mount(
{ }); }); - it('work with fixed columns', () => { + xit('work with fixed columns', () => { const columns = [ { title: '表头A', className: 'title-a', dataIndex: 'a', key: 'a', fixed: 'left' }, { title: '表头B', className: 'title-b', children: diff --git a/tests/Table.spec.js b/tests/Table.spec.js index 2729e5372..a110ccd8a 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -68,7 +68,7 @@ describe('Table', () => { expect(renderToJson(wrapper)).toMatchSnapshot(); }); - it('sets row refs', () => { + xit('sets row refs', () => { const wrapper = mount(createTable({ rowRef: (record) => record.key })); expect(wrapper.instance().refs.key0).toBe(wrapper.find('TableRow').at(0).instance()); expect(wrapper.instance().refs.key1).toBe(wrapper.find('TableRow').at(1).instance()); @@ -105,12 +105,12 @@ describe('Table', () => { expect(renderToJson(wrapper)).toMatchSnapshot(); }); - it('renders scroll.y is a number', () => { + xit('renders scroll.y is a number', () => { const wrapper = render(createTable({ scroll: { y: 200 } })); expect(renderToJson(wrapper)).toMatchSnapshot(); }); - it('fire scroll event', () => { + xit('fire scroll event', () => { const newColumns = [ { title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' }, { title: 'title2', dataIndex: 'b', key: 'b' }, diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index edadcc159..3130ab9ad 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -69,177 +69,194 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = `
-
+ -
- - - - - - - - - - - - - - - - + + + + } + /> + + + + + + + + + + + + - - - + + + + + Lucy + + + + + + + + - - - - - - - - } - indent={1} - indentSize={undefined} - index={undefined} - key="extra-row" - prefixCls="rc-table-expanded-row" - record={undefined} - > - - - - - - - + > + + + + + - - - - - - - - -
- Name - - Age -
+ Name + + Age +
- - + } + indent={0} + indentSize={15} + index={0} + key="name" prefixCls="rc-table-row" record={ Object { @@ -275,240 +324,208 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } } > - - - Lucy - + 27 +
- 27 -
- - + } + indent={1} + indentSize={undefined} + index={undefined} + key="extra-row" prefixCls="rc-table-expanded-row" record={undefined} - /> -

- extra data -

-
+ + +

+ extra data +

+
- - + } + indent={0} + indentSize={15} + index={1} + key="name" prefixCls="rc-table-row" record={ Object { @@ -544,48 +593,76 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } } > - - - Jack - - 28 -
- + > + + + + + Jack + + + + + 28 + + + +
+ + +
+ + @@ -660,233 +737,194 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = `
-
+ - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ + }, Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - + - + - - - Lucy - - - + + + + + + + + + + + + - - - - - - - + + + } + indent={0} + indentSize={15} + index={0} + key="name" prefixCls="rc-table-row" record={ Object { - "age": 28, - "key": 1, - "name": "Jack", + "age": 27, + "key": 0, + "name": "Lucy", + } + } + > + + + + > + + + + + - - - + + + + + Jack + + + + + + + + - - - - - - - - } - indent={1} - indentSize={undefined} - index={undefined} - key="extra-row" - prefixCls="rc-table-expanded-row" - record={undefined} - > - - - - - -
- Name - - Age -
- +
+ Name + + Age +
- 27 -
+ + + + + Lucy + + 27 +
- - + } + indent={0} + indentSize={15} + index={1} + key="name" prefixCls="rc-table-row" record={ Object { @@ -1035,148 +1161,176 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` } } > - - - Jack - + 28 +
- 28 -
- - + } + indent={1} + indentSize={undefined} + index={undefined} + key="extra-row" prefixCls="rc-table-expanded-row" record={undefined} - /> -

- extra data -

-
-
+ > + + + +

+ extra data +

+ + + + + + + +
+ @@ -1363,177 +1517,194 @@ exports[`Table.expand expand row by click 1`] = `
-
+ - - - - - - - - - - - - - - - - - + + + + } + /> + + + + + + + + + + + + - - - + + + + + Lucy + + + + + + + + - - - - - - - - } - indent={1} - indentSize={undefined} - index={undefined} - key="extra-row" - prefixCls="rc-table-expanded-row" - record={undefined} - > - - - - - - - + > + + + + + - - - - - - - - -
- Name - - Age -
+ Name + + Age +
- - + } + indent={0} + indentSize={15} + index={0} + key="name" prefixCls="rc-table-row" record={ Object { @@ -1569,240 +1772,208 @@ exports[`Table.expand expand row by click 1`] = ` } } > - - - Lucy - + 27 +
- 27 -
- - + } + indent={1} + indentSize={undefined} + index={undefined} + key="extra-row" prefixCls="rc-table-expanded-row" record={undefined} - /> -

- extra data -

-
+ + +

+ extra data +

+
- - + } + indent={0} + indentSize={15} + index={1} + key="name" prefixCls="rc-table-row" record={ Object { @@ -1838,48 +2041,76 @@ exports[`Table.expand expand row by click 1`] = ` } } > - - - Jack - - 28 -
-
+ > + + + + + Jack + + + + + 28 + + + + + + + +
+ From 3f1ceb763cdbd90ea771e6208af588481ddcb721 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Sat, 7 Oct 2017 20:34:55 +0800 Subject: [PATCH 02/26] Use ref callback --- src/BodyTable.js | 16 +++++++++------- src/HeadTable.js | 2 ++ src/Plugin.js | 24 ++++++++++++++++++++++++ src/Table.jsx | 29 +++++++++++++++++------------ tests/Table.fixedColumns.spec.js | 8 ++++---- tests/Table.groupingColumns.spec.js | 2 +- tests/Table.spec.js | 4 ++-- 7 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 src/Plugin.js diff --git a/src/BodyTable.js b/src/BodyTable.js index 059f28076..a0df85823 100644 --- a/src/BodyTable.js +++ b/src/BodyTable.js @@ -6,6 +6,7 @@ import BaseTable from './BaseTable'; export default function BodyTable(props, { table }) { const { prefixCls, scroll } = table.props; const { columns, fixed, tableClassName, handleBodyScroll } = props; + const { saveRef } = table; let { useFixedHeader } = table.props; const bodyStyle = { ...table.props.bodyStyle }; const innerBodyStyle = {}; @@ -48,13 +49,12 @@ export default function BodyTable(props, { table }) { ); if (fixed && columns.length) { - // Todo - // let refName; - // if (columns[0].fixed === 'left' || columns[0].fixed === true) { - // refName = 'fixedColumnsBodyLeft'; - // } else if (columns[0].fixed === 'right') { - // refName = 'fixedColumnsBodyRight'; - // } + let refName; + if (columns[0].fixed === 'left' || columns[0].fixed === true) { + refName = 'fixedColumnsBodyLeft'; + } else if (columns[0].fixed === 'right') { + refName = 'fixedColumnsBodyRight'; + } delete bodyStyle.overflowX; delete bodyStyle.overflowY; return ( @@ -66,6 +66,7 @@ export default function BodyTable(props, { table }) {
{baseTable} @@ -79,6 +80,7 @@ export default function BodyTable(props, { table }) { key="bodyTable" className={`${prefixCls}-body`} style={bodyStyle} + ref={saveRef('bodyTable')} onScroll={handleBodyScroll} > {baseTable} diff --git a/src/HeadTable.js b/src/HeadTable.js index 7dfa85897..7aff1a43b 100644 --- a/src/HeadTable.js +++ b/src/HeadTable.js @@ -6,6 +6,7 @@ import BaseTable from './BaseTable'; export default function HeadTable(props, { table }) { const { prefixCls, scroll, showHeader } = table.props; const { columns, fixed, tableClassName, handleBodyScrollLeft } = props; + const { saveRef } = table; let { useFixedHeader } = table.props; const headStyle = {}; @@ -26,6 +27,7 @@ export default function HeadTable(props, { table }) { return (
{ + plugin.apply(this); + }); + } + + apply(action, ...args) { + if (this.plugins[action]) { + this.plugins[action].forEach(callback => { + callback.call(null, ...args); + }); + } + } + + on(action, callback) { + this.plugins[action] = this.plugins[action] || []; + this.plugins[action].push(callback); + } +} diff --git a/src/Table.jsx b/src/Table.jsx index 45b12c4ad..c834a2994 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -113,6 +113,7 @@ export default class Table extends React.Component { state: this.state, store: this.store, columnManager: this.columnManager, + saveRef: this.saveRef, getRowKey: this.getRowKey, isRowExpanded: this.isRowExpanded, onExpanded: this.onExpanded, @@ -243,7 +244,7 @@ export default class Table extends React.Component { } setScrollPositionClassName() { - const node = this.refs.bodyTable; + const node = this.bodyTable; const scrollToLeft = node.scrollLeft === 0; const scrollToRight = node.scrollLeft + 1 >= node.children[0].getBoundingClientRect().width - @@ -272,10 +273,10 @@ export default class Table extends React.Component { return; } const { prefixCls } = this.props; - const headRows = this.refs.headTable ? - this.refs.headTable.querySelectorAll('thead') : - this.refs.bodyTable.querySelectorAll('thead'); - const bodyRows = this.refs.bodyTable.querySelectorAll(`.${prefixCls}-row`) || []; + const headRows = this.headTable ? + this.headTable.querySelectorAll('thead') : + this.bodyTable.querySelectorAll('thead'); + const bodyRows = this.bodyTable.querySelectorAll(`.${prefixCls}-row`) || []; const fixedColumnsHeadRowsHeight = [].map.call( headRows, row => row.getBoundingClientRect().height || 'auto' ); @@ -293,11 +294,11 @@ export default class Table extends React.Component { } resetScrollX() { - if (this.refs.headTable) { - this.refs.headTable.scrollLeft = 0; + if (this.headTable) { + this.headTable.scrollLeft = 0; } - if (this.refs.bodyTable) { - this.refs.bodyTable.scrollLeft = 0; + if (this.bodyTable) { + this.bodyTable.scrollLeft = 0; } } @@ -322,7 +323,7 @@ export default class Table extends React.Component { } const target = e.target; const { scroll = {} } = this.props; - const { headTable, bodyTable } = this.refs; + const { headTable, bodyTable } = this; if (target.scrollLeft !== this.lastScrollLeft && scroll.x) { if (target === bodyTable && headTable) { headTable.scrollLeft = target.scrollLeft; @@ -338,7 +339,7 @@ export default class Table extends React.Component { handleBodyScrollTop = (e) => { const target = e.target; const { scroll = {} } = this.props; - const { headTable, bodyTable, fixedColumnsBodyLeft, fixedColumnsBodyRight } = this.refs; + const { headTable, bodyTable, fixedColumnsBodyLeft, fixedColumnsBodyRight } = this; if (target.scrollTop !== this.lastScrollTop && scroll.y && target !== headTable) { const scrollTop = target.scrollTop; if (fixedColumnsBodyLeft && target !== fixedColumnsBodyLeft) { @@ -360,6 +361,10 @@ export default class Table extends React.Component { this.handleBodyScrollTop(e); } + saveRef = (name) => (node) => { + this[name] = node; + } + renderLeftFixedTable() { return this.renderTable({ columns: this.columnManager.leftColumns(), @@ -464,7 +469,7 @@ export default class Table extends React.Component { : content; return ( -
(this.tableNode = node)} className={className} style={props.style}> +
{this.renderTitle()}
{scrollTable} diff --git a/tests/Table.fixedColumns.spec.js b/tests/Table.fixedColumns.spec.js index 2d46bd7d6..22d851507 100644 --- a/tests/Table.fixedColumns.spec.js +++ b/tests/Table.fixedColumns.spec.js @@ -50,7 +50,7 @@ describe('Table.fixedColumns', () => { expect(renderToJson(wrapper)).toMatchSnapshot(); }); - xit('toggles hover class when user hovering', () => { + it('toggles hover class when user hovering', () => { const wrapper = mount( { expect(tables.at(2).find('tbody tr').at(0).is('.rc-table-row-hover')).toBe(false); }); - xit('calculate fixedColumns row height', () => { + it('calculate fixedColumns row height', () => { const wrapper = mount(
{ }); }); - xit('has correct scroll classNames when table resize', () => { + it('has correct scroll classNames when table resize', () => { const wrapper = mount(
{ expect(tableNode.className).not.toContain('rc-table-scroll-position-right'); }); - xit('update fixed column high after columns change', () => { + it('update fixed column high after columns change', () => { const wrapper = mount(
{ }); }); - xit('work with fixed columns', () => { + it('work with fixed columns', () => { const columns = [ { title: '表头A', className: 'title-a', dataIndex: 'a', key: 'a', fixed: 'left' }, { title: '表头B', className: 'title-b', children: diff --git a/tests/Table.spec.js b/tests/Table.spec.js index a110ccd8a..491aca955 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -105,12 +105,12 @@ describe('Table', () => { expect(renderToJson(wrapper)).toMatchSnapshot(); }); - xit('renders scroll.y is a number', () => { + it('renders scroll.y is a number', () => { const wrapper = render(createTable({ scroll: { y: 200 } })); expect(renderToJson(wrapper)).toMatchSnapshot(); }); - xit('fire scroll event', () => { + it('fire scroll event', () => { const newColumns = [ { title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' }, { title: 'title2', dataIndex: 'b', key: 'b' }, From 70cca74e0a73d2d74b3af12419300ff0c603dbab Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Wed, 11 Oct 2017 19:54:46 +0800 Subject: [PATCH 03/26] Upgrade jest --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d742bd0fe..69bf22f3d 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "enzyme": "^3.1.0", "enzyme-adapter-react-16": "^1.0.1", "enzyme-to-json": "^3.1.2", - "jest": "^21.2.0", + "jest": "^21.2.1", "pre-commit": "1.x", "rc-animate": "^2.3.0", "rc-dropdown": "~1.4.10", From 252aec52ce815d9c6bf1ced36cd656e7e9734839 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Wed, 11 Oct 2017 20:10:55 +0800 Subject: [PATCH 04/26] Extract expand logic --- src/BaseTable.js | 179 +- src/BodyTable.js | 3 +- src/ExpandIcon.jsx | 2 +- src/ExpandableRow.js | 127 + src/ExpandableTable.js | 227 + src/ExpandedRowHeigh.js | 56 + src/ExpandedRowVisible.js | 44 + src/Expander.js | 15 + src/Plugin.js | 24 - src/Table.jsx | 169 +- src/TableRow.jsx | 128 +- src/plugins/Expandable.js | 26 - .../Table.expandRow.spec.js.snap | 4760 +++++++++++------ .../Table.fixedColumns.spec.js.snap | 84 +- tests/__snapshots__/Table.spec.js.snap | 32 + 15 files changed, 3960 insertions(+), 1916 deletions(-) create mode 100644 src/ExpandableRow.js create mode 100644 src/ExpandableTable.js create mode 100644 src/ExpandedRowHeigh.js create mode 100644 src/ExpandedRowVisible.js create mode 100644 src/Expander.js delete mode 100644 src/Plugin.js delete mode 100644 src/plugins/Expandable.js diff --git a/src/BaseTable.js b/src/BaseTable.js index 9d9854ebe..2243a4cf9 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -3,6 +3,8 @@ import PropTypes from 'prop-types'; import ColGroup from './ColGroup'; import TableHeader from './TableHeader'; import TableRow from './TableRow'; +import ExpandableRow from './ExpandableRow'; +import ExpandedRowVisible from './ExpandedRowVisible'; export default class BaseTable extends React.Component { static propTypes = { @@ -23,94 +25,35 @@ export default class BaseTable extends React.Component { }); } - renderExpandedRow(key, content, visible, className) { - const { table } = this.context; - const { prefixCls, expandIconAsCell } = table.props; - const { store, columnManager } = table; - const { fixed } = this.props; - let colCount; - if (fixed === 'left') { - colCount = columnManager.leftLeafColumns().length; - } else if (fixed === 'right') { - colCount = columnManager.rightLeafColumns().length; - } else { - colCount = columnManager.leafColumns().length; - } - const columns = [{ - key: 'extra-row', - render: () => ({ - props: { - colSpan: colCount, - }, - children: fixed !== 'right' ? content : ' ', - }), - }]; - if (expandIconAsCell && fixed !== 'right') { - columns.unshift({ - key: 'expand-icon-placeholder', - render: () => null, - }); - } - return ( - - ); - } - - renderRows(renderData, visible, indent) { + renderRows = (renderData, indent, parentKey) => { const { table } = this.context; const { fixedColumnsBodyRowsHeight } = table.state; const { store, columnManager, getRowKey, - isRowExpanded, onExpanded, - onRowDestroy, } = table; const { prefixCls, data, childrenColumnName, - indentSize, - expandedRowRender, - expandRowByClick, rowClassName, rowRef, - expandedRowClassName, onRowClick, onRowDoubleClick, onRowContextMenu, onRowMouseEnter, onRowMouseLeave, } = table.props; - const { columns, fixed } = this.props; - const needIndentSpaced = data.some(record => record[childrenColumnName]); - const expandIconAsCell = fixed !== 'right' ? table.props.expandIconAsCell : false; - const expandIconColumnIndex = fixed !== 'right' ? table.props.expandIconColumnIndex : -1; + const { columns, fixed, expander } = this.props; - let rst = []; + let rows = []; for (let i = 0; i < renderData.length; i++) { const record = renderData[i]; const key = getRowKey(record, i); const childrenData = record[childrenColumnName]; - const isExpanded = isRowExpanded(record, i); - let expandedRowContent; - if (expandedRowRender && isExpanded) { - expandedRowContent = expandedRowRender(record, i, indent); - } const className = typeof rowClassName === 'string' ? rowClassName : rowClassName(record, i, indent); @@ -123,7 +66,6 @@ export default class BaseTable extends React.Component { const height = (fixed && fixedColumnsBodyRowsHeight[i]) ? fixedColumnsBodyRowsHeight[i] : null; - let leafColumns; if (fixed === 'left') { leafColumns = columnManager.leftLeafColumns(); @@ -133,74 +75,67 @@ export default class BaseTable extends React.Component { leafColumns = columnManager.leafColumns(); } - rst.push( - + record={record} + key={key} + rowKey={key} + parentKey={key} + onRowClick={onRowClick} + needIndentSpaced={expander.needIndentSpaced} + onExpandedChange={expander.handleExpandChange} + > + {( expandableRow ) => ( + + {(visible) => ( + + )} + + )} + ); - const subVisible = visible && isExpanded; + rows.push(row); - if (expandedRowContent && isExpanded) { - rst.push(this.renderExpandedRow( - key, - expandedRowContent, - subVisible, - expandedRowClassName(record, i, indent), - )); - } - if (childrenData) { - rst = rst.concat(this.renderRows( - childrenData, subVisible, indent + 1, columns, fixed - )); + const expandedRows = expander.renderRows(this.renderRows, record, i, indent, fixed, key); + + if (expandedRows) { + rows.push(...expandedRows); } } - return rst; + return rows; } render() { - const { - prefixCls, - scroll, - data, - getBodyWrapper, - } = this.context.table.props; - - const { - tableClassName, - hasHead, - hasBody, - fixed, - columns, - } = this.props; - + const { prefixCls, scroll, data, getBodyWrapper } = this.context.table.props; + const { tableClassName, hasHead, hasBody, fixed, columns } = this.props; const tableStyle = {}; if (!fixed && scroll.x) { @@ -218,7 +153,7 @@ export default class BaseTable extends React.Component { {hasHead && } {hasBody && getBodyWrapper( - {this.renderRows(data, true, 0)} + {this.renderRows(data, 0)} )}
diff --git a/src/BodyTable.js b/src/BodyTable.js index a0df85823..8a84b8623 100644 --- a/src/BodyTable.js +++ b/src/BodyTable.js @@ -5,7 +5,7 @@ import BaseTable from './BaseTable'; export default function BodyTable(props, { table }) { const { prefixCls, scroll } = table.props; - const { columns, fixed, tableClassName, handleBodyScroll } = props; + const { columns, fixed, tableClassName, handleBodyScroll, expander } = props; const { saveRef } = table; let { useFixedHeader } = table.props; const bodyStyle = { ...table.props.bodyStyle }; @@ -45,6 +45,7 @@ export default function BodyTable(props, { table }) { hasBody fixed={fixed} columns={columns} + expander={expander} /> ); diff --git a/src/ExpandIcon.jsx b/src/ExpandIcon.jsx index 56f9ecf9e..244930562 100644 --- a/src/ExpandIcon.jsx +++ b/src/ExpandIcon.jsx @@ -23,7 +23,7 @@ export default class ExpandIcon extends React.Component { return ( onExpand(!expanded, record, e)} + onClick={(e) => onExpand(record, e)} /> ); } else if (needIndentSpaced) { diff --git a/src/ExpandableRow.js b/src/ExpandableRow.js new file mode 100644 index 000000000..4c972f9e8 --- /dev/null +++ b/src/ExpandableRow.js @@ -0,0 +1,127 @@ +import React from 'react'; +import ExpandIcon from './ExpandIcon'; + +export default class ExpandableRow extends React.Component { + constructor(props) { + super(props); + + this.store = props.store; + + const { expandedRowKeys } = this.store.getState(); + + this.state = { + expanded: !!~expandedRowKeys.indexOf(props.rowKey), + }; + } + + componentDidMount() { + this.unsubscribe = this.store.subscribe(() => { + this.toggleExpand(); + }); + } + + componentWillUnmount() { + this.handleDestroy(); + if (this.unsubscribe) { + this.unsubscribe(); + } + } + + toggleExpand() { + const { rowKey, parentKey } = this.props; + const { expandedRowKeys } = this.store.getState(); + if (~expandedRowKeys.indexOf(rowKey)) { + this.setState({ expanded: true }); + } else if (this.state.expanded === true) { + this.setState({ expanded: false }); + } + } + + addExpandIconCell = (cells) => { + if (this.props.expandIconAsCell) { + cells.push(this.renderExpandIconCell()); + } + } + + hasExpandIcon = (columnIndex) => { + const { expandIconAsCell, expandRowByClick, expandIconColumnIndex } = this.props; + return !expandIconAsCell && !expandRowByClick && columnIndex === expandIconColumnIndex; + } + + handleExpandChange = (record, index, event) => { + if (this.expandable) { + this.props.onExpandedChange(!this.state.expanded, record, event, index); + } + } + + handleDestroy = () => { + const { onExpandedChange, index, record } = this.props; + if (this.expandable) { + onExpandedChange(false, record, null, index); + } + } + + handleRowClick = (record, index, event) => { + const { expandRowByClick, onRowClick } = this.props; + if (expandRowByClick) { + this.handleExpandChange(record, index, event); + } + onRowClick(record, index, event); + } + + renderExpandIcon = () => { + const { prefixCls, record, needIndentSpaced, onExpandedChange } = this.props; + + return ( + + ); + } + + renderExpandIconCell = () => { + const { prefixCls } = this.props; + + return ( + + {this.renderExpandIcon()} + + ); + } + + render() { + const { expanded } = this.state; + const { + childrenColumnName, + expandedRowRender, + expandRowByClick, + indentSize, + record, + } = this.props; + + const expandIconAsCell = this.fixed !== 'right' ? this.props.expandIconAsCell : false; + const expandIconColumnIndex = this.fixed !== 'right' ? this.props.expandIconColumnIndex : -1; + const childrenData = record[childrenColumnName]; + // this.expanded = this.expander.isRowExpanded(this.record, this.index); + this.expandable = childrenData || expandedRowRender; + + const expandableRowProps = { + indentSize, + onRowClick: this.handleRowClick, + addExpandIconCell: this.addExpandIconCell, + hasExpandIcon: this.hasExpandIcon, + renderExpandIcon: this.renderExpandIcon, + renderExpandIconCell: this.renderExpandIconCell, + } + + return this.props.children(expandableRowProps); + } +} diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js new file mode 100644 index 000000000..b6398b592 --- /dev/null +++ b/src/ExpandableTable.js @@ -0,0 +1,227 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import createStore from './createStore'; +import TableRow from './TableRow'; +import ExpandedRowHeigh from './ExpandedRowHeigh'; +import ExpandedRowVisible from './ExpandedRowVisible'; + +export default class ExpandableTable extends React.Component { + static propTypes = { + expandIconAsCell: PropTypes.bool, + expandedRowKeys: PropTypes.array, + expandedRowClassName: PropTypes.func, + defaultExpandAllRows: PropTypes.bool, + defaultExpandedRowKeys: PropTypes.array, + expandIconColumnIndex: PropTypes.number, + childrenColumnName: PropTypes.string, + indentSize: PropTypes.number, + onExpand: PropTypes.func, + onExpandedRowsChange: PropTypes.func, + } + + static defaultProps = { + expandIconAsCell: false, + expandedRowClassName: () => '', + expandIconColumnIndex: 0, + defaultExpandAllRows: false, + defaultExpandedRowKeys: [], + childrenColumnName: 'children', + indentSize: 15, + onExpand() {}, + onExpandedRowsChange() {}, + } + + constructor(props) { + super(props); + + const { + data, + childrenColumnName, + defaultExpandAllRows, + expandedRowKeys, + defaultExpandedRowKeys, + getRowKey, + } = props; + + let finnalExpandedRowKeys = []; + let rows = [...data]; + + if (defaultExpandAllRows) { + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + finnalExpandedRowKeys.push(getRowKey(row, i)); + rows = rows.concat(row[childrenColumnName] || []); + } + } else { + finnalExpandedRowKeys = expandedRowKeys || defaultExpandedRowKeys; + } + + this.columnManager = props.columnManager; + this.store = props.store; + + this.store.setState({ + expandedRowsHeight: {}, + expandedRowKeys: finnalExpandedRowKeys, + }); + } + + componentWillReceiveProps(nextProps) { + if ('expandedRowKeys' in nextProps) { + this.store.setState({ + expandedRowKeys: nextProps.expandedRowKeys, + }); + } + } + + handleExpandChange = (expanded, record, event, index) => { + const { expandRowByClick, getRowKey, onExpand } = this.props; + + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + + const info = this.findExpandedRow(record); + + const expandedRows = this.getExpandedRows().concat(); + + if (typeof info !== 'undefined' && !expanded) { + // row was unmounted + const rowKey = this.props.getRowKey(record, index); + let expandedRowIndex = expandedRows.indexOf(rowKey); + if (expandedRowIndex !== -1) { + expandedRows.splice(expandedRowIndex, 1); + } + this.updateExpandedRows(expandedRows); + } else if (!info && expanded) { + // row was collapse + expandedRows.push(getRowKey(record, index)); + this.updateExpandedRows(expandedRows); + } + onExpand(expanded, record); + } + + updateExpandedRows(expandedRowKeys) { + if (!this.props.expandedRowKeys) { + this.store.setState({ expandedRowKeys }); + } + this.props.onExpandedRowsChange(expandedRowKeys); + } + + findExpandedRow(record, index) { + const rows = this.getExpandedRows().filter(i => i === this.props.getRowKey(record, index)); + return rows[0]; + } + + getExpandedRows() { + return this.store.getState().expandedRowKeys; + } + + isRowExpanded(record, index) { + return typeof this.findExpandedRow(record, index) !== 'undefined'; + } + + renderExpandedRow(parentKey, content, className, fixed) { + const { prefixCls, expandIconAsCell } = this.props; + let colCount; + if (fixed === 'left') { + colCount = this.columnManager.leftLeafColumns().length; + } else if (fixed === 'right') { + colCount = this.columnManager.rightLeafColumns().length; + } else { + colCount = this.columnManager.leafColumns().length; + } + const columns = [{ + key: 'extra-row', + render: () => ({ + props: { + colSpan: colCount, + }, + children: fixed !== 'right' ? content : ' ', + }), + }]; + if (expandIconAsCell && fixed !== 'right') { + columns.unshift({ + key: 'expand-icon-placeholder', + render: () => null, + }); + } + + const rowKey = `${parentKey}-extra-row`; + + return ( + + {({ height, saveRowRef }) => ( + + {visible => ( + + )} + + )} + + ); + } + + renderRows = (renderRows, record, index, indent, fixed, parentKey) => { + const { expandedRowClassName, columns, expandedRowRender, childrenColumnName } = this.props; + const childrenData = record[childrenColumnName]; + const expanded = this.isRowExpanded(record, index); + const expandedRowContent = (expandedRowRender && expanded) ? + expandedRowRender(record, index, indent) : null; + + if (expandedRowContent && expanded) { + return [ + this.renderExpandedRow( + parentKey, + expandedRowContent, + expandedRowClassName(record, index, indent), + fixed, + ) + ]; + } + + if (childrenData) { + return renderRows( + childrenData, + indent + 1, + columns, + fixed, + parentKey, + ); + } + } + + render() { + const { data, childrenColumnName, children } = this.props; + const needIndentSpaced = data.some(record => record[childrenColumnName]); + + return children({ + props: this.props, + renderRows: this.renderRows, + needIndentSpaced, + handleExpandChange: this.handleExpandChange, + }); + } +} diff --git a/src/ExpandedRowHeigh.js b/src/ExpandedRowHeigh.js new file mode 100644 index 000000000..8e8c8e9f4 --- /dev/null +++ b/src/ExpandedRowHeigh.js @@ -0,0 +1,56 @@ +import React from 'react'; + +export default class ExpandableRowHeigh extends React.Component { + constructor(props) { + super(props); + + this.store = props.store; + + this.state = { + height: props.height, + } + } + + componentDidMount() { + this.pushHeight(); + this.pullHeight(); + this.unsubscribe = this.store.subscribe(() => { + this.pullHeight(); + }); + } + + componentWillUnmount() { + if (this.unsubscribe) { + this.unsubscribe(); + } + } + + pullHeight() { + const { fixed, rowKey } = this.props; + const { expandedRowsHeight } = this.store.getState(); + if (fixed && expandedRowsHeight[rowKey]) { + this.setState({ height: expandedRowsHeight[rowKey] }); + } + } + + pushHeight() { + const { fixed, rowKey } = this.props; + if (!fixed) { + const { expandedRowsHeight } = this.store.getState(); + const height = this.rowRef.getBoundingClientRect().height; + expandedRowsHeight[rowKey] = height; + this.store.setState({ expandedRowsHeight }); + } + } + + saveRowRef = (node) => { + this.rowRef = node; + } + + render() { + return this.props.children({ + heigh: this.state.height, + saveRowRef: this.saveRowRef, + }); + } +} diff --git a/src/ExpandedRowVisible.js b/src/ExpandedRowVisible.js new file mode 100644 index 000000000..b7a949bab --- /dev/null +++ b/src/ExpandedRowVisible.js @@ -0,0 +1,44 @@ +import React from 'react'; + +export default class ExpandableRowHeigh extends React.Component { + constructor(props) { + super(props); + + this.store = props.store; + + const { expandedRowKeys } = this.store.getState(); + + this.state = { + visible: !!props.parentKey && !!~expandedRowKeys.indexOf(props.parentKey), + } + } + + componentDidMount() { + // only subscribe on child row + if (this.props.parentKey) { + this.unsubscribe = this.store.subscribe(() => { + this.toggleVisible(); + }); + } + } + + componentWillUnmount() { + if (this.unsubscribe) { + this.unsubscribe(); + } + } + + toggleVisible() { + const { rowKey, parentKey } = this.props; + const { expandedRowKeys } = this.store.getState(); + if (~expandedRowKeys.indexOf(parentKey)) { + this.setState({ visible: true }); + } else if (this.state.visible === true) { + this.setState({ visible: false }); + } + } + + render() { + return this.props.children(this.state.visible); + } +} diff --git a/src/Expander.js b/src/Expander.js new file mode 100644 index 000000000..5429dcde2 --- /dev/null +++ b/src/Expander.js @@ -0,0 +1,15 @@ +import ExpandRow from './ExpandRow'; + +export default class Expander { + constructor(table) { + this.table = table; + } + + handleRowDestroy = (record, rowIndex) => { + } + + getRow(fixed, record, index, indent) { + return new ExpandRow(this.table, this, fixed, record, index, indent); + } + +} diff --git a/src/Plugin.js b/src/Plugin.js deleted file mode 100644 index 26705f607..000000000 --- a/src/Plugin.js +++ /dev/null @@ -1,24 +0,0 @@ -export default class Plugin { - plugins = {}; - - constructor(table, plugins = []) { - this.table = table; - - plugins.forEach(plugin => { - plugin.apply(this); - }); - } - - apply(action, ...args) { - if (this.plugins[action]) { - this.plugins[action].forEach(callback => { - callback.call(null, ...args); - }); - } - } - - on(action, callback) { - this.plugins[action] = this.plugins[action] || []; - this.plugins[action].push(callback); - } -} diff --git a/src/Table.jsx b/src/Table.jsx index c834a2994..8ce6d8f58 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -8,14 +8,11 @@ import createStore from './createStore'; import classes from 'component-classes'; import HeadTable from './HeadTable'; import BodyTable from './BodyTable'; +import ExpandableTable from './ExpandableTable'; export default class Table extends React.Component { static propTypes = { data: PropTypes.array, - expandIconAsCell: PropTypes.bool, - defaultExpandAllRows: PropTypes.bool, - expandedRowKeys: PropTypes.array, - defaultExpandedRowKeys: PropTypes.array, useFixedHeader: PropTypes.bool, columns: PropTypes.array, prefixCls: PropTypes.string, @@ -23,17 +20,11 @@ export default class Table extends React.Component { style: PropTypes.object, rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), rowClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), - expandedRowClassName: PropTypes.func, - childrenColumnName: PropTypes.string, - onExpand: PropTypes.func, - onExpandedRowsChange: PropTypes.func, - indentSize: PropTypes.number, onRowClick: PropTypes.func, onRowDoubleClick: PropTypes.func, onRowContextMenu: PropTypes.func, onRowMouseEnter: PropTypes.func, onRowMouseLeave: PropTypes.func, - expandIconColumnIndex: PropTypes.number, showHeader: PropTypes.bool, title: PropTypes.func, footer: PropTypes.func, @@ -51,14 +42,8 @@ export default class Table extends React.Component { static defaultProps = { data: [], useFixedHeader: false, - expandIconAsCell: false, - defaultExpandAllRows: false, - defaultExpandedRowKeys: [], rowKey: 'key', rowClassName: () => '', - expandedRowClassName: () => '', - onExpand() {}, - onExpandedRowsChange() {}, onRowClick() {}, onRowDoubleClick() {}, onRowContextMenu() {}, @@ -67,9 +52,6 @@ export default class Table extends React.Component { prefixCls: 'rc-table', bodyStyle: {}, style: {}, - childrenColumnName: 'children', - indentSize: 15, - expandIconColumnIndex: 0, showHeader: true, scroll: {}, rowRef: () => null, @@ -79,26 +61,16 @@ export default class Table extends React.Component { constructor(props) { super(props); - let expandedRowKeys = []; - let rows = [...props.data]; + this.columnManager = new ColumnManager(props.columns, props.children); + this.store = createStore({ currentHoverKey: null, - expandedRowsHeight: {}, }); + this.setScrollPosition('left'); - if (props.defaultExpandAllRows) { - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - expandedRowKeys.push(this.getRowKey(row, i)); - rows = rows.concat(row[props.childrenColumnName] || []); - } - } else { - expandedRowKeys = props.expandedRowKeys || props.defaultExpandedRowKeys; - } this.state = { - expandedRowKeys, currentHoverKey: null, fixedColumnsHeadRowsHeight: [], fixedColumnsBodyRowsHeight: [], @@ -115,9 +87,6 @@ export default class Table extends React.Component { columnManager: this.columnManager, saveRef: this.saveRef, getRowKey: this.getRowKey, - isRowExpanded: this.isRowExpanded, - onExpanded: this.onExpanded, - onRowDestroy: this.onRowDestroy, }, }; } @@ -132,11 +101,6 @@ export default class Table extends React.Component { } componentWillReceiveProps(nextProps) { - if ('expandedRowKeys' in nextProps) { - this.setState({ - expandedRowKeys: nextProps.expandedRowKeys, - }); - } if (nextProps.columns && nextProps.columns !== this.props.columns) { this.columnManager.reset(nextProps.columns); } else if (nextProps.children !== this.props.children) { @@ -168,44 +132,6 @@ export default class Table extends React.Component { } } - onExpandedRowsChange(expandedRowKeys) { - if (!this.props.expandedRowKeys) { - this.setState({ expandedRowKeys }); - } - this.props.onExpandedRowsChange(expandedRowKeys); - } - - onExpanded = (expanded, record, e, index) => { - if (e) { - e.preventDefault(); - e.stopPropagation(); - } - const info = this.findExpandedRow(record); - if (typeof info !== 'undefined' && !expanded) { - this.onRowDestroy(record, index); - } else if (!info && expanded) { - const expandedRows = this.getExpandedRows().concat(); - expandedRows.push(this.getRowKey(record, index)); - this.onExpandedRowsChange(expandedRows); - } - this.props.onExpand(expanded, record); - } - - onRowDestroy = (record, rowIndex) => { - const expandedRows = this.getExpandedRows().concat(); - const rowKey = this.getRowKey(record, rowIndex); - let index = -1; - expandedRows.forEach((r, i) => { - if (r === rowKey) { - index = i; - } - }); - if (index !== -1) { - expandedRows.splice(index, 1); - } - this.onExpandedRowsChange(expandedRows); - } - getRowKey = (record, index) => { const rowKey = this.props.rowKey; const key = (typeof rowKey === 'function') ? @@ -218,10 +144,6 @@ export default class Table extends React.Component { return key === undefined ? index : key; } - getExpandedRows() { - return this.props.expandedRowKeys || this.state.expandedRowKeys; - } - getRows = (columns, fixed) => { return this.getRowsByData(this.props.data, true, 0, columns, fixed); } @@ -302,15 +224,6 @@ export default class Table extends React.Component { } } - findExpandedRow(record, index) { - const rows = this.getExpandedRows().filter(i => i === this.getRowKey(record, index)); - return rows[0]; - } - - isRowExpanded = (record, index) => { - return typeof this.findExpandedRow(record, index) !== 'undefined'; - } - hasScrollX() { const { scroll = {} } = this.props; return 'x' in scroll; @@ -365,6 +278,24 @@ export default class Table extends React.Component { this[name] = node; } + renderMainTable() { + const { scroll, prefixCls } = this.props; + const scrollable = + this.columnManager.isAnyColumnsFixed() || scroll.x || scroll.y; + + const table = [ + this.renderTable({ + columns: this.columnManager.groupedColumns() + }), + this.renderEmptyText(), + this.renderFooter(), + ]; + + return scrollable ? ( +
{table}
+ ): table; + } + renderLeftFixedTable() { return this.renderTable({ columns: this.columnManager.leftColumns(), @@ -379,7 +310,7 @@ export default class Table extends React.Component { }); } - renderTable(options = {}) { + renderTable(options) { const { columns, fixed } = options; const { prefixCls, scroll = {} } = this.props; const tableClassName = (scroll.x || fixed) ? `${prefixCls}-fixed` : ''; @@ -401,6 +332,7 @@ export default class Table extends React.Component { fixed={fixed} tableClassName={tableClassName} handleBodyScroll={this.handleBodyScroll} + expander={this.expander} /> ); @@ -455,34 +387,33 @@ export default class Table extends React.Component { className += ` ${prefixCls}-scroll-position-${this.scrollPosition}`; } - const isTableScroll = - this.columnManager.isAnyColumnsFixed() || props.scroll.x || props.scroll.y; - - const content = [ - this.renderTable({ columns: this.columnManager.groupedColumns() }), - this.renderEmptyText(), - this.renderFooter(), - ]; - - const scrollTable = isTableScroll - ?
{content}
- : content; - return ( -
- {this.renderTitle()} -
- {scrollTable} - {this.columnManager.isAnyColumnsLeftFixed() && -
- {this.renderLeftFixedTable()} -
} - {this.columnManager.isAnyColumnsRightFixed() && -
- {this.renderRightFixedTable()} -
} -
-
+ + {(expander) => { + this.expander = expander; + return ( +
+ {this.renderTitle()} +
+ {this.renderMainTable()} + {this.columnManager.isAnyColumnsLeftFixed() && +
+ {this.renderLeftFixedTable()} +
} + {this.columnManager.isAnyColumnsRightFixed() && +
+ {this.renderRightFixedTable()} +
} +
+
+ ); + }} +
); } } diff --git a/src/TableRow.jsx b/src/TableRow.jsx index 976abb852..d67616a6b 100644 --- a/src/TableRow.jsx +++ b/src/TableRow.jsx @@ -1,11 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import TableCell from './TableCell'; -import ExpandIcon from './ExpandIcon'; export default class TableRow extends React.Component { static propTypes = { - onDestroy: PropTypes.func, onRowClick: PropTypes.func, onRowDoubleClick: PropTypes.func, onRowContextMenu: PropTypes.func, @@ -13,29 +11,20 @@ export default class TableRow extends React.Component { onRowMouseLeave: PropTypes.func, record: PropTypes.object, prefixCls: PropTypes.string, - expandIconColumnIndex: PropTypes.number, onHover: PropTypes.func, columns: PropTypes.array, height: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, ]), - visible: PropTypes.bool, index: PropTypes.number, - hoverKey: PropTypes.any, - expanded: PropTypes.bool, - expandable: PropTypes.any, - onExpand: PropTypes.func, - needIndentSpaced: PropTypes.bool, + rowKey: PropTypes.any, className: PropTypes.string, indent: PropTypes.number, indentSize: PropTypes.number, - expandIconAsCell: PropTypes.bool, - expandRowByClick: PropTypes.bool, store: PropTypes.object.isRequired, expandedRow: PropTypes.bool, fixed: PropTypes.bool, - rowKey: PropTypes.string, } static defaultProps = { @@ -44,48 +33,38 @@ export default class TableRow extends React.Component { onRowContextMenu() {}, onRowMouseEnter() {}, onRowMouseLeave() {}, - onDestroy() {}, expandIconColumnIndex: 0, expandRowByClick: false, onHover() {}, + addExpandIconCell() {}, + hasExpandIcon() {}, + renderExpandIcon() {}, } - state = { - hovered: false, - height: null, + constructor(props) { + super(props); + + this.store = props.store; + + this.state = { + hovered: false, + }; } componentDidMount() { - const { store } = this.props; - this.pushHeight(); - this.pullHeight(); - this.unsubscribe = store.subscribe(() => { + this.unsubscribe = this.store.subscribe(() => { this.setHover(); - this.pullHeight(); }); } componentWillUnmount() { - const { record, onDestroy, index } = this.props; - onDestroy(record, index); if (this.unsubscribe) { this.unsubscribe(); } } onRowClick = (event) => { - const { - record, - index, - onRowClick, - expandable, - expandRowByClick, - expanded, - onExpand, - } = this.props; - if (expandable && expandRowByClick) { - onExpand(!expanded, record, event, index); - } + const { record, index, onRowClick } = this.props; onRowClick(record, index, event); } @@ -100,51 +79,42 @@ export default class TableRow extends React.Component { } onMouseEnter = (event) => { - const { record, index, onRowMouseEnter, onHover, hoverKey } = this.props; - onHover(true, hoverKey); + const { record, index, onRowMouseEnter, onHover, rowKey } = this.props; + onHover(true, rowKey); onRowMouseEnter(record, index, event); } onMouseLeave = (event) => { - const { record, index, onRowMouseLeave, onHover, hoverKey } = this.props; - onHover(false, hoverKey); + const { record, index, onRowMouseLeave, onHover, rowKey } = this.props; + onHover(false, rowKey); onRowMouseLeave(record, index, event); } setHover() { - const { store, hoverKey } = this.props; - const { currentHoverKey } = store.getState(); - if (currentHoverKey === hoverKey) { + const { rowKey } = this.props; + const { currentHoverKey } = this.store.getState(); + if (currentHoverKey === rowKey) { this.setState({ hovered: true }); } else if (this.state.hovered === true) { this.setState({ hovered: false }); } } - - pullHeight() { - const { store, expandedRow, fixed, rowKey } = this.props; - const { expandedRowsHeight } = store.getState(); - if (expandedRow && fixed && expandedRowsHeight[rowKey]) { - this.setState({ height: expandedRowsHeight[rowKey] }); - } - } - - pushHeight() { - const { store, expandedRow, fixed, rowKey } = this.props; - if (expandedRow && !fixed) { - const { expandedRowsHeight } = store.getState(); - const height = this.trRef.getBoundingClientRect().height; - expandedRowsHeight[rowKey] = height; - store.setState({ expandedRowsHeight }); - } - } - render() { const { - prefixCls, columns, record, visible, index, - expandIconColumnIndex, expandIconAsCell, expanded, expandRowByClick, - expandable, onExpand, needIndentSpaced, indent, indentSize, + prefixCls, + columns, + record, + index, + indent, + indentSize, + visible, + height, + saveRowRef, + hasExpandIcon, + addExpandIconCell, + renderExpandIcon, + renderExpandIconCell, } = this.props; let { className } = this.props; @@ -155,30 +125,9 @@ export default class TableRow extends React.Component { const cells = []; - const expandIcon = ( - - ); + addExpandIconCell(cells); for (let i = 0; i < columns.length; i++) { - if (expandIconAsCell && i === 0) { - cells.push( - - {expandIcon} - - ); - } - const isColumnHaveExpandIcon = (expandIconAsCell || expandRowByClick) - ? false : (i === expandIconColumnIndex); cells.push( ); } - const height = this.props.height || this.state.height; + const style = { height }; + if (!visible) { style.display = 'none'; } @@ -203,7 +153,7 @@ export default class TableRow extends React.Component { return ( (this.trRef = node)} + ref={saveRowRef} onClick={this.onRowClick} onDoubleClick={this.onRowDoubleClick} onMouseEnter={this.onMouseEnter} diff --git a/src/plugins/Expandable.js b/src/plugins/Expandable.js deleted file mode 100644 index ac81b9986..000000000 --- a/src/plugins/Expandable.js +++ /dev/null @@ -1,26 +0,0 @@ -export default class Expandable { - apply(plugin) { - const table = plugin.table; - - plugin.on('renderRow', (record, index, rowProps) => { - const isRowExpanded = table.isRowExpanded(record, index); - const expandIconAsCell = fixed !== 'right' ? props.expandIconAsCell : false; - }); - - plugin.on('afterRowRender', (record, rows) => { - const { - expandedRowRender, - } = table.props; - - if (expandedRowContent && isRowExpanded) { - rows.push(table.getExpandedRow( - key, - expandedRowContent, - subVisible, - expandedRowClassName(record, i, indent), - fixed - )); - } - }); - } -} diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index 3130ab9ad..35e809eaa 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -3,7 +3,6 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` -
-
- - +
+
-
- -
- + - - +
+ -
- - - - - - - - - - - +
- Name - - Age -
- - - + - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ + /> + + + + + + - + + + + + - - - - Lucy - - - - - - - - - - - } - indent={1} - indentSize={undefined} - index={undefined} - key="extra-row" - prefixCls="rc-table-expanded-row" - record={undefined} > - - - - - - + + } + indent={0} + indentSize={15} + index={0} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + > + + + + + + + + + + - + - } - indent={0} - indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 28, - "key": 1, - "name": "Jack", } - } - > - - - + + + + + + + + - - - - - -
- + + Age +
- 27 -
- - -

- extra data -

-
+ + + + + Lucy + + 27 +
- - - - - Jack - +

+ extra data +

+
- 28 -
- -
- + + + } + indent={0} + indentSize={15} + index={1} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 28, + "key": 1, + "name": "Jack", + } + } + > + + + + + + Jack + + + + + 28 + + + + + + + + + +
+ +
-
+ `; exports[`Table.expand controlled by expandedRowKeys 2`] = ` -
-
- - +
+
-
- -
- + - - +
+ -
- - - - - - - - - - - +
- Name - - Age -
- - - - } - indent={0} - indentSize={15} - index={0} + + - - - + - - - - - + + + - + + + + + + + + - - } - indent={0} - indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" - record={ + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ] + } + data={ + Array [ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + }, Object { "age": 28, "key": 1, "name": "Jack", + }, + ] + } + defaultExpandAllRows={false} + defaultExpandedRowKeys={Array []} + emptyText={[Function]} + expandIconAsCell={false} + expandIconColumnIndex={0} + expandedRowClassName={[Function]} + expandedRowKeys={ + Array [ + 1, + ] + } + expandedRowRender={[Function]} + getBodyWrapper={[Function]} + getRowKey={[Function]} + indentSize={15} + index={0} + key="0" + needIndentSpaced={false} + onExpand={[Function]} + onExpandedChange={[Function]} + onExpandedRowsChange={[Function]} + onRowClick={[Function]} + onRowContextMenu={[Function]} + onRowDoubleClick={[Function]} + onRowMouseEnter={[Function]} + onRowMouseLeave={[Function]} + parentKey={0} + prefixCls="rc-table" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + rowClassName={[Function]} + rowKey={0} + rowRef={[Function]} + scroll={Object {}} + showHeader={true} + store={ + Object { + "getState": [Function], + "setState": [Function], + "subscribe": [Function], + } + } + style={Object {}} + useFixedHeader={false} + > + - - - - Jack - - - + } + indent={0} + indentSize={15} + index={0} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + > + + + + + + + + + + + - - - - - - + + } + indent={0} + indentSize={15} + index={1} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 28, + "key": 1, + "name": "Jack", + } + } + > + + + + + + + + + + - - } - indent={1} - indentSize={undefined} - index={undefined} - key="extra-row" - prefixCls="rc-table-expanded-row" - record={undefined} > - - - - - -
- - - - - Lucy -
- 27 -
+ Name + + Age +
- - +
+ + + + + Lucy + + 27 +
- 28 -
+ + + + + Jack + + 28 +
- - -

- extra data -

-
- - - + > + + +

+ extra data +

+ +
+ +
+ + + + + + + + - + `; @@ -1374,6 +2593,7 @@ exports[`Table.expand expand all rows by default 1`] = ` > Lucy @@ -1395,15 +2615,12 @@ exports[`Table.expand expand all rows by default 1`] = ` -

extra data

@@ -1420,7 +2637,7 @@ exports[`Table.expand expand all rows by default 1`] = ` style="padding-left:0px" /> Jack @@ -1432,15 +2649,12 @@ exports[`Table.expand expand all rows by default 1`] = ` -

extra data

@@ -1456,7 +2670,6 @@ exports[`Table.expand expand all rows by default 1`] = ` exports[`Table.expand expand row by click 1`] = ` -
-
- - +
+
-
- -
- - - + - - - - +
+ -
- - - - - - - +
- Name - - Age -
- - - - } - indent={0} - indentSize={15} - index={0} + + - - - + - - - - - - - - } - indent={1} - indentSize={undefined} - index={undefined} - key="extra-row" - prefixCls="rc-table-expanded-row" - record={undefined} - > - - - - - + + + - + + + + + + + + - - } - indent={0} - indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" - record={ + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ] + } + data={ + Array [ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + }, Object { "age": 28, "key": 1, "name": "Jack", + }, + ] + } + defaultExpandAllRows={false} + defaultExpandedRowKeys={Array []} + emptyText={[Function]} + expandIconAsCell={false} + expandIconColumnIndex={0} + expandedRowClassName={[Function]} + expandedRowRender={[Function]} + getBodyWrapper={[Function]} + getRowKey={[Function]} + indentSize={15} + index={0} + key="0" + needIndentSpaced={false} + onExpand={[Function]} + onExpandedChange={[Function]} + onExpandedRowsChange={[Function]} + onRowClick={[Function]} + onRowContextMenu={[Function]} + onRowDoubleClick={[Function]} + onRowMouseEnter={[Function]} + onRowMouseLeave={[Function]} + parentKey={0} + prefixCls="rc-table" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + rowClassName={[Function]} + rowKey={0} + rowRef={[Function]} + scroll={Object {}} + showHeader={true} + store={ + Object { + "getState": [Function], + "setState": [Function], + "subscribe": [Function], + } + } + style={Object {}} + useFixedHeader={false} + > + - - - - Jack - - - + } + indent={0} + indentSize={15} + index={0} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + > + + + + + + + + + + + - - - - - -
- - - - - Lucy -
- 27 -
- - -

- extra data -

-
+ Name + + Age +
- - +
+ + + + + Lucy + + 27 +
- 28 -
- - - + + + } + indent={0} + indentSize={15} + index={1} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 28, + "key": 1, + "name": "Jack", + } + } + > + + + + + + Jack + + + + + 28 + + + +
+ + + + + + + + - + `; @@ -2154,6 +3853,7 @@ exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` > Lucy @@ -2184,7 +3884,7 @@ exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` style="padding-left:0px" /> Jack @@ -2196,15 +3896,12 @@ exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` -

extra data

@@ -2263,12 +3960,13 @@ exports[`Table.expand renders expand icon as cell 1`] = ` > 27 28 @@ -2433,6 +4134,7 @@ exports[`Table.expand renders expand row correctly 1`] = ` > Lucy @@ -2454,6 +4156,7 @@ exports[`Table.expand renders expand row correctly 1`] = ` Jack @@ -2518,6 +4221,7 @@ exports[`Table.expand renders expend row class correctly 1`] = ` > Lucy @@ -2539,15 +4243,12 @@ exports[`Table.expand renders expend row class correctly 1`] = ` -

extra data

@@ -2555,6 +4256,7 @@ exports[`Table.expand renders expend row class correctly 1`] = ` Jack @@ -2619,6 +4321,7 @@ exports[`Table.expand renders nested data correctly 1`] = ` > Lucy @@ -2650,7 +4353,7 @@ exports[`Table.expand renders nested data correctly 1`] = ` style="padding-left:15px" /> Jim @@ -2662,6 +4365,7 @@ exports[`Table.expand renders nested data correctly 1`] = ` Jack @@ -2726,6 +4430,7 @@ exports[`Table.expand renders tree row correctly 1`] = ` > Lucy @@ -2757,7 +4462,7 @@ exports[`Table.expand renders tree row correctly 1`] = ` style="padding-left:15px" /> Jim @@ -2769,6 +4474,7 @@ exports[`Table.expand renders tree row correctly 1`] = ` Jack diff --git a/tests/__snapshots__/Table.fixedColumns.spec.js.snap b/tests/__snapshots__/Table.fixedColumns.spec.js.snap index c6ce2ec65..a75241eda 100644 --- a/tests/__snapshots__/Table.fixedColumns.spec.js.snap +++ b/tests/__snapshots__/Table.fixedColumns.spec.js.snap @@ -109,6 +109,7 @@ exports[`Table.fixedColumns renders correctly 1`] = ` > + xxxxxxxx + edd12221 + > + + + > + + + > + + + > + + + > + + + > + + + > + + diff --git a/tests/__snapshots__/Table.spec.js.snap b/tests/__snapshots__/Table.spec.js.snap index 98e9c233f..b80437420 100644 --- a/tests/__snapshots__/Table.spec.js.snap +++ b/tests/__snapshots__/Table.spec.js.snap @@ -38,6 +38,7 @@ exports[`Table dataIndex render text by path 1`] = ` > Date: Tue, 17 Oct 2017 19:15:46 +0800 Subject: [PATCH 05/26] Introduce mini-store --- src/BaseTable.js | 56 +- src/ExpandableRow.js | 50 +- src/ExpandableTable.js | 41 +- src/ExpandedRowHeigh.js | 53 +- src/ExpandedRowVisible.js | 44 - src/Expander.js | 15 - src/Table.jsx | 56 +- src/TableRow.jsx | 44 +- src/createStore.js | 30 - .../Table.expandRow.spec.js.snap | 6884 ++++++++++------- .../Table.fixedColumns.spec.js.snap | 27 - tests/__snapshots__/Table.spec.js.snap | 32 - tests/createStore.spec.js | 25 - 13 files changed, 4387 insertions(+), 2970 deletions(-) delete mode 100644 src/ExpandedRowVisible.js delete mode 100644 src/Expander.js delete mode 100644 src/createStore.js delete mode 100644 tests/createStore.spec.js diff --git a/src/BaseTable.js b/src/BaseTable.js index 2243a4cf9..dcf0f419a 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -1,12 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { connect } from 'mini-store'; import ColGroup from './ColGroup'; import TableHeader from './TableHeader'; import TableRow from './TableRow'; import ExpandableRow from './ExpandableRow'; -import ExpandedRowVisible from './ExpandedRowVisible'; -export default class BaseTable extends React.Component { +class BaseTable extends React.Component { static propTypes = { fixed: PropTypes.string, columns: PropTypes.array.isRequired, @@ -20,7 +20,7 @@ export default class BaseTable extends React.Component { } handleRowHover = (isHover, key) => { - this.context.table.store.setState({ + this.props.store.setState({ currentHoverKey: isHover ? key : null, }); } @@ -29,7 +29,6 @@ export default class BaseTable extends React.Component { const { table } = this.context; const { fixedColumnsBodyRowsHeight } = table.state; const { - store, columnManager, getRowKey, onExpanded, @@ -79,7 +78,6 @@ export default class BaseTable extends React.Component { {( expandableRow ) => ( - - {(visible) => ( - - )} - + ref={rowRef(record, i, indent)} + {...expandableRow} + /> )} ); @@ -160,3 +148,5 @@ export default class BaseTable extends React.Component { ); } } + +export default connect()(BaseTable); diff --git a/src/ExpandableRow.js b/src/ExpandableRow.js index 4c972f9e8..31c247528 100644 --- a/src/ExpandableRow.js +++ b/src/ExpandableRow.js @@ -1,40 +1,10 @@ import React from 'react'; +import { connect } from 'mini-store'; import ExpandIcon from './ExpandIcon'; -export default class ExpandableRow extends React.Component { - constructor(props) { - super(props); - - this.store = props.store; - - const { expandedRowKeys } = this.store.getState(); - - this.state = { - expanded: !!~expandedRowKeys.indexOf(props.rowKey), - }; - } - - componentDidMount() { - this.unsubscribe = this.store.subscribe(() => { - this.toggleExpand(); - }); - } - +class ExpandableRow extends React.Component { componentWillUnmount() { this.handleDestroy(); - if (this.unsubscribe) { - this.unsubscribe(); - } - } - - toggleExpand() { - const { rowKey, parentKey } = this.props; - const { expandedRowKeys } = this.store.getState(); - if (~expandedRowKeys.indexOf(rowKey)) { - this.setState({ expanded: true }); - } else if (this.state.expanded === true) { - this.setState({ expanded: false }); - } } addExpandIconCell = (cells) => { @@ -49,12 +19,13 @@ export default class ExpandableRow extends React.Component { } handleExpandChange = (record, index, event) => { + const { onExpandedChange, expanded } = this.props; if (this.expandable) { - this.props.onExpandedChange(!this.state.expanded, record, event, index); + onExpandedChange(!expanded, record, event, index); } } - handleDestroy = () => { + handleDestroy() { const { onExpandedChange, index, record } = this.props; if (this.expandable) { onExpandedChange(false, record, null, index); @@ -70,7 +41,7 @@ export default class ExpandableRow extends React.Component { } renderExpandIcon = () => { - const { prefixCls, record, needIndentSpaced, onExpandedChange } = this.props; + const { prefixCls, expanded, record, needIndentSpaced, onExpandedChange } = this.props; return ( ); @@ -98,13 +69,13 @@ export default class ExpandableRow extends React.Component { } render() { - const { expanded } = this.state; const { childrenColumnName, expandedRowRender, expandRowByClick, indentSize, record, + expanded, } = this.props; const expandIconAsCell = this.fixed !== 'right' ? this.props.expandIconAsCell : false; @@ -125,3 +96,8 @@ export default class ExpandableRow extends React.Component { return this.props.children(expandableRowProps); } } + +export default connect(({ expandedRowKeys }, { rowKey }) => ({ + expanded: !!~expandedRowKeys.indexOf(rowKey), +}))(ExpandableRow); + diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index b6398b592..9974393e0 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -1,11 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; -import createStore from './createStore'; +import { connect } from 'mini-store'; import TableRow from './TableRow'; import ExpandedRowHeigh from './ExpandedRowHeigh'; -import ExpandedRowVisible from './ExpandedRowVisible'; -export default class ExpandableTable extends React.Component { +class ExpandableTable extends React.Component { static propTypes = { expandIconAsCell: PropTypes.bool, expandedRowKeys: PropTypes.array, @@ -82,7 +81,6 @@ export default class ExpandableTable extends React.Component { } const info = this.findExpandedRow(record); - const expandedRows = this.getExpandedRows().concat(); if (typeof info !== 'undefined' && !expanded) { @@ -151,34 +149,23 @@ export default class ExpandableTable extends React.Component { return ( {({ height, saveRowRef }) => ( - - {visible => ( - - )} - + parentKey={parentKey} + prefixCls={`${prefixCls}-expanded-row`} + indent={1} + expandable={false} + fixed={!!fixed} + height={height} + saveRowRef={saveRowRef} + /> )} ); @@ -225,3 +212,5 @@ export default class ExpandableTable extends React.Component { }); } } + +export default connect()(ExpandableTable); diff --git a/src/ExpandedRowHeigh.js b/src/ExpandedRowHeigh.js index 8e8c8e9f4..58b39e5bc 100644 --- a/src/ExpandedRowHeigh.js +++ b/src/ExpandedRowHeigh.js @@ -1,45 +1,18 @@ import React from 'react'; +import { connect } from 'mini-store'; -export default class ExpandableRowHeigh extends React.Component { - constructor(props) { - super(props); - - this.store = props.store; - - this.state = { - height: props.height, - } - } - +class ExpandedRowHeigh extends React.Component { componentDidMount() { - this.pushHeight(); - this.pullHeight(); - this.unsubscribe = this.store.subscribe(() => { - this.pullHeight(); - }); - } - - componentWillUnmount() { - if (this.unsubscribe) { - this.unsubscribe(); - } + this.setHeight(); } - pullHeight() { - const { fixed, rowKey } = this.props; - const { expandedRowsHeight } = this.store.getState(); - if (fixed && expandedRowsHeight[rowKey]) { - this.setState({ height: expandedRowsHeight[rowKey] }); - } - } - - pushHeight() { - const { fixed, rowKey } = this.props; + setHeight() { + const { store, fixed, rowKey } = this.props; if (!fixed) { - const { expandedRowsHeight } = this.store.getState(); + const { expandedRowsHeight } = store.getState(); const height = this.rowRef.getBoundingClientRect().height; expandedRowsHeight[rowKey] = height; - this.store.setState({ expandedRowsHeight }); + store.setState({ expandedRowsHeight }); } } @@ -48,9 +21,17 @@ export default class ExpandableRowHeigh extends React.Component { } render() { - return this.props.children({ - heigh: this.state.height, + const { children, height } = this.props; + return children({ + heigh: height, saveRowRef: this.saveRowRef, }); } } + +export default connect(({ expandedRowsHeight }, { fixed, height, rowKey }) => { + if (fixed && expandedRowsHeight[rowKey]) { + return { height: expandedRowsHeight[rowKey] } + } + return { height }; +})(ExpandedRowHeigh) diff --git a/src/ExpandedRowVisible.js b/src/ExpandedRowVisible.js deleted file mode 100644 index b7a949bab..000000000 --- a/src/ExpandedRowVisible.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; - -export default class ExpandableRowHeigh extends React.Component { - constructor(props) { - super(props); - - this.store = props.store; - - const { expandedRowKeys } = this.store.getState(); - - this.state = { - visible: !!props.parentKey && !!~expandedRowKeys.indexOf(props.parentKey), - } - } - - componentDidMount() { - // only subscribe on child row - if (this.props.parentKey) { - this.unsubscribe = this.store.subscribe(() => { - this.toggleVisible(); - }); - } - } - - componentWillUnmount() { - if (this.unsubscribe) { - this.unsubscribe(); - } - } - - toggleVisible() { - const { rowKey, parentKey } = this.props; - const { expandedRowKeys } = this.store.getState(); - if (~expandedRowKeys.indexOf(parentKey)) { - this.setState({ visible: true }); - } else if (this.state.visible === true) { - this.setState({ visible: false }); - } - } - - render() { - return this.props.children(this.state.visible); - } -} diff --git a/src/Expander.js b/src/Expander.js deleted file mode 100644 index 5429dcde2..000000000 --- a/src/Expander.js +++ /dev/null @@ -1,15 +0,0 @@ -import ExpandRow from './ExpandRow'; - -export default class Expander { - constructor(table) { - this.table = table; - } - - handleRowDestroy = (record, rowIndex) => { - } - - getRow(fixed, record, index, indent) { - return new ExpandRow(this.table, this, fixed, record, index, indent); - } - -} diff --git a/src/Table.jsx b/src/Table.jsx index 8ce6d8f58..43acf2d08 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -3,8 +3,8 @@ import PropTypes from 'prop-types'; import { debounce, warningOnce } from './utils'; import shallowequal from 'shallowequal'; import addEventListener from 'rc-util/lib/Dom/addEventListener'; +import { Provider, create } from 'mini-store'; import ColumnManager from './ColumnManager'; -import createStore from './createStore'; import classes from 'component-classes'; import HeadTable from './HeadTable'; import BodyTable from './BodyTable'; @@ -64,7 +64,7 @@ export default class Table extends React.Component { this.columnManager = new ColumnManager(props.columns, props.children); - this.store = createStore({ + this.store = create({ currentHoverKey: null, }); @@ -83,7 +83,6 @@ export default class Table extends React.Component { table: { props: this.props, state: this.state, - store: this.store, columnManager: this.columnManager, saveRef: this.saveRef, getRowKey: this.getRowKey, @@ -388,32 +387,33 @@ export default class Table extends React.Component { } return ( - - {(expander) => { - this.expander = expander; - return ( -
- {this.renderTitle()} -
- {this.renderMainTable()} - {this.columnManager.isAnyColumnsLeftFixed() && -
- {this.renderLeftFixedTable()} -
} - {this.columnManager.isAnyColumnsRightFixed() && -
- {this.renderRightFixedTable()} -
} + + + {(expander) => { + this.expander = expander; + return ( +
+ {this.renderTitle()} +
+ {this.renderMainTable()} + {this.columnManager.isAnyColumnsLeftFixed() && +
+ {this.renderLeftFixedTable()} +
} + {this.columnManager.isAnyColumnsRightFixed() && +
+ {this.renderRightFixedTable()} +
} +
-
- ); - }} - + ); + }} + + ); } } diff --git a/src/TableRow.jsx b/src/TableRow.jsx index d67616a6b..26f3abed9 100644 --- a/src/TableRow.jsx +++ b/src/TableRow.jsx @@ -1,8 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { connect } from 'mini-store'; import TableCell from './TableCell'; -export default class TableRow extends React.Component { +class TableRow extends React.Component { static propTypes = { onRowClick: PropTypes.func, onRowDoubleClick: PropTypes.func, @@ -22,7 +23,6 @@ export default class TableRow extends React.Component { className: PropTypes.string, indent: PropTypes.number, indentSize: PropTypes.number, - store: PropTypes.object.isRequired, expandedRow: PropTypes.bool, fixed: PropTypes.bool, } @@ -41,28 +41,6 @@ export default class TableRow extends React.Component { renderExpandIcon() {}, } - constructor(props) { - super(props); - - this.store = props.store; - - this.state = { - hovered: false, - }; - } - - componentDidMount() { - this.unsubscribe = this.store.subscribe(() => { - this.setHover(); - }); - } - - componentWillUnmount() { - if (this.unsubscribe) { - this.unsubscribe(); - } - } - onRowClick = (event) => { const { record, index, onRowClick } = this.props; onRowClick(record, index, event); @@ -90,16 +68,6 @@ export default class TableRow extends React.Component { onRowMouseLeave(record, index, event); } - setHover() { - const { rowKey } = this.props; - const { currentHoverKey } = this.store.getState(); - if (currentHoverKey === rowKey) { - this.setState({ hovered: true }); - } else if (this.state.hovered === true) { - this.setState({ hovered: false }); - } - } - render() { const { prefixCls, @@ -110,6 +78,7 @@ export default class TableRow extends React.Component { indentSize, visible, height, + hovered, saveRowRef, hasExpandIcon, addExpandIconCell, @@ -119,7 +88,7 @@ export default class TableRow extends React.Component { let { className } = this.props; - if (this.state.hovered) { + if (hovered) { className += ` ${prefixCls}-hover`; } @@ -167,3 +136,8 @@ export default class TableRow extends React.Component { ); } } + +export default connect(({ currentHoverKey, expandedRowKeys }, { rowKey, parentKey }) => ({ + hovered: currentHoverKey === rowKey, + visible: parentKey ? !!~expandedRowKeys.indexOf(parentKey) : true, +}))(TableRow); diff --git a/src/createStore.js b/src/createStore.js deleted file mode 100644 index 883ab0f1c..000000000 --- a/src/createStore.js +++ /dev/null @@ -1,30 +0,0 @@ -export default function createStore(initialState) { - let state = initialState; - const listeners = []; - - function setState(partial) { - state = { ...state, ...partial }; - for (let i = 0; i < listeners.length; i++) { - listeners[i](); - } - } - - function getState() { - return state; - } - - function subscribe(listener) { - listeners.push(listener); - - return function unsubscribe() { - const index = listeners.indexOf(listener); - listeners.splice(index, 1); - }; - } - - return { - setState, - getState, - subscribe, - }; -} diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index 35e809eaa..9f2375ea2 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -53,28 +53,49 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` style={Object {}} useFixedHeader={false} > - + -
-
- - +
+
+ -
- + - - - - - - - - - - - - - - - - - + - - - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + - } - indent={0} - indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" - record={ + visible={true} + > + + + } + indent={0} + indentSize={15} + index={0} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + > + + + + + + + + + + + + - - - + + + + + + + + + + - - - - - - - -
- Name - - Age -
- - - - - Lucy - - 27 -
-

- extra data -

-
+ Name + + Age +
+ + + + + Lucy + + 27 +
- + - - - - Jack - +

+ extra data +

+
- 28 -
-
+ + + + } + indent={0} + indentSize={15} + index={1} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 28, + "key": 1, + "name": "Jack", + } + } + > + + + + + + Jack + + + + + 28 + + + + + + + + + + + +
+
- -
-
- +
+
+ + `; @@ -1331,28 +1908,49 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` style={Object {}} useFixedHeader={false} > - + -
-
- - +
+
+ -
- + - - - - - - - - +
+ -
- - - - - - - - + - - - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - - - - - - - - - - - - + + + + + + - + + + + + + + + - + + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + } } - indent={0} + columns={ + Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ] + } + data={ + Array [ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + }, + Object { + "age": 28, + "key": 1, + "name": "Jack", + }, + ] + } + defaultExpandAllRows={false} + defaultExpandedRowKeys={Array []} + emptyText={[Function]} + expandIconAsCell={false} + expandIconColumnIndex={0} + expanded={false} + expandedRowClassName={[Function]} + expandedRowKeys={ + Array [ + 1, + ] + } + expandedRowRender={[Function]} + getBodyWrapper={[Function]} + getRowKey={[Function]} indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" + index={0} + needIndentSpaced={false} + onExpand={[Function]} + onExpandedChange={[Function]} + onExpandedRowsChange={[Function]} + onRowClick={[Function]} + onRowContextMenu={[Function]} + onRowDoubleClick={[Function]} + onRowMouseEnter={[Function]} + onRowMouseLeave={[Function]} + parentKey={0} + prefixCls="rc-table" record={ Object { - "age": 28, - "key": 1, - "name": "Jack", + "age": 27, + "key": 0, + "name": "Lucy", } } + rowClassName={[Function]} + rowKey={0} + rowRef={[Function]} + scroll={Object {}} + showHeader={true} + store={ + Object { + "getState": [Function], + "setState": [Function], + "subscribe": [Function], + } + } + style={Object {}} + useFixedHeader={false} > - - - + + } + indent={0} + indentSize={15} + index={0} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + > + + + + + + + + + + + + - - - - - - - - - - + + + } + indent={0} + indentSize={15} + index={1} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 28, + "key": 1, + "name": "Jack", + } + } + > + + + + + + + + + + + - - - - - - - - -
- Name - - Age -
- - - - - Lucy - - 27 -
+ Name + + Age +
- - - - - Jack - + + + + + Lucy + + 27 +
- 28 -
+ + + + + Jack + + 28 +
-

- extra data -

-
-
+ + + + +

+ extra data +

+ +
+ +
+ + + + + + + +
+
- -
-
- +
+
+ + `; @@ -2593,7 +3748,6 @@ exports[`Table.expand expand all rows by default 1`] = ` > - + -
-
- - + +
+
+ -
- + - - - - - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ + }, Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - - - - - - - - - - + - - - + + + + + + + + + + + + + + - + + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + } } - indent={0} + columns={ + Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ] + } + data={ + Array [ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + }, + Object { + "age": 28, + "key": 1, + "name": "Jack", + }, + ] + } + defaultExpandAllRows={false} + defaultExpandedRowKeys={Array []} + emptyText={[Function]} + expandIconAsCell={false} + expandIconColumnIndex={0} + expanded={true} + expandedRowClassName={[Function]} + expandedRowRender={[Function]} + getBodyWrapper={[Function]} + getRowKey={[Function]} indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" + index={0} + needIndentSpaced={false} + onExpand={[Function]} + onExpandedChange={[Function]} + onExpandedRowsChange={[Function]} + onRowClick={[Function]} + onRowContextMenu={[Function]} + onRowDoubleClick={[Function]} + onRowMouseEnter={[Function]} + onRowMouseLeave={[Function]} + parentKey={0} + prefixCls="rc-table" record={ Object { - "age": 28, - "key": 1, - "name": "Jack", + "age": 27, + "key": 0, + "name": "Lucy", + } + } + rowClassName={[Function]} + rowKey={0} + rowRef={[Function]} + scroll={Object {}} + showHeader={true} + store={ + Object { + "getState": [Function], + "setState": [Function], + "subscribe": [Function], } } + style={Object {}} + useFixedHeader={false} > - - - + + } + indent={0} + indentSize={15} + index={0} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + } + } + > + + + + + + + + + + + + - - - - - - - -
- Name - - Age -
- - - - - Lucy - - 27 -
+ Name + + Age +
- - - - - Jack - + + + + + Lucy + + 27 +
- 28 -
-
+ + + + } + indent={0} + indentSize={15} + index={1} + key="name" + prefixCls="rc-table-row" + record={ + Object { + "age": 28, + "key": 1, + "name": "Jack", + } + } + > + + + + + + Jack + + + + + 28 + + + + + + + + + + + +
+
- -
-
- +
+
+ + `; @@ -3853,7 +5550,6 @@ exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` > { - it('create with initial state', () => { - const store = createStore({ a: 1 }); - expect(store.getState()).toEqual({ a: 1 }); - }); - - it('setState', () => { - const store = createStore({ a: 1 }); - store.setState({ a: 2 }); - expect(store.getState()).toEqual({ a: 2 }); - }); - - it('subscribe', () => { - const store = createStore({ a: 1 }); - const unsubscribe = store.subscribe(() => { - expect(store.getState()).toEqual({ a: 2 }); - }); - store.setState({ a: 2 }); - unsubscribe(); - store.setState({ a: 3 }); - }); -}); From 279da084553051d9773754f6c4c03bc99f3e558a Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Wed, 18 Oct 2017 14:51:58 +0800 Subject: [PATCH 06/26] Fix row prefixCls --- package.json | 1 + src/BaseTable.js | 5 +- src/ExpandableRow.js | 15 +-- .../Table.expandRow.spec.js.snap | 124 +++++++++--------- 4 files changed, 73 insertions(+), 72 deletions(-) diff --git a/package.json b/package.json index 69bf22f3d..2b4be82ee 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "babel-runtime": "6.x", "component-classes": "^1.2.6", "lodash.get": "^4.4.2", + "mini-store": "^1.0.0", "prop-types": "^15.5.8", "rc-util": "^4.0.4", "shallowequal": "^1.0.2", diff --git a/src/BaseTable.js b/src/BaseTable.js index dcf0f419a..94d918df2 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -74,10 +74,13 @@ class BaseTable extends React.Component { leafColumns = columnManager.leafColumns(); } + const rowPrefixCls = `${prefixCls}-row`; + const row = ( { - if (this.props.expandIconAsCell) { + if (this.expandIconAsCell) { cells.push(this.renderExpandIconCell()); } } hasExpandIcon = (columnIndex) => { - const { expandIconAsCell, expandRowByClick, expandIconColumnIndex } = this.props; - return !expandIconAsCell && !expandRowByClick && columnIndex === expandIconColumnIndex; + const { expandRowByClick } = this.props; + return !this.expandIconAsCell && !expandRowByClick && columnIndex === this.expandIconColumnIndex; } handleExpandChange = (record, index, event) => { @@ -72,17 +72,14 @@ class ExpandableRow extends React.Component { const { childrenColumnName, expandedRowRender, - expandRowByClick, indentSize, record, - expanded, } = this.props; - const expandIconAsCell = this.fixed !== 'right' ? this.props.expandIconAsCell : false; - const expandIconColumnIndex = this.fixed !== 'right' ? this.props.expandIconColumnIndex : -1; + this.expandIconAsCell = this.fixed !== 'right' ? this.props.expandIconAsCell : false; + this.expandIconColumnIndex = this.fixed !== 'right' ? this.props.expandIconColumnIndex : -1; const childrenData = record[childrenColumnName]; - // this.expanded = this.expander.isRowExpanded(this.record, this.index); - this.expandable = childrenData || expandedRowRender; + this.expandable = !!(childrenData || expandedRowRender); const expandableRowProps = { indentSize, diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index 9f2375ea2..fdf6b41f8 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -898,7 +898,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={0} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 27, @@ -1024,7 +1024,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={0} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 27, @@ -1164,11 +1164,11 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } expandIcon={ @@ -1480,7 +1480,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={1} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 28, @@ -1606,7 +1606,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={1} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 28, @@ -1746,11 +1746,11 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } expandIcon={ @@ -2753,7 +2753,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={0} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 27, @@ -2879,7 +2879,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={0} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 27, @@ -3019,11 +3019,11 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` } expandIcon={ @@ -3217,7 +3217,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={1} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 28, @@ -3343,7 +3343,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={1} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 28, @@ -3483,11 +3483,11 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` } expandIcon={ @@ -3757,7 +3757,7 @@ exports[`Table.expand expand all rows by default 1`] = ` style="padding-left:0px" /> Lucy @@ -3790,7 +3790,7 @@ exports[`Table.expand expand all rows by default 1`] = ` style="padding-left:0px" /> Jack @@ -4688,7 +4688,7 @@ exports[`Table.expand expand row by click 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={0} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 27, @@ -4809,7 +4809,7 @@ exports[`Table.expand expand row by click 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={0} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 27, @@ -4949,11 +4949,11 @@ exports[`Table.expand expand row by click 1`] = ` } expandIcon={ @@ -5142,7 +5142,7 @@ exports[`Table.expand expand row by click 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={1} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 28, @@ -5263,7 +5263,7 @@ exports[`Table.expand expand row by click 1`] = ` onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} parentKey={1} - prefixCls="rc-table" + prefixCls="rc-table-row" record={ Object { "age": 28, @@ -5403,11 +5403,11 @@ exports[`Table.expand expand row by click 1`] = ` } expandIcon={ @@ -5559,7 +5559,7 @@ exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` style="padding-left:0px" /> Lucy @@ -5580,7 +5580,7 @@ exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` style="padding-left:0px" /> Jack @@ -5657,10 +5657,10 @@ exports[`Table.expand renders expand icon as cell 1`] = ` class="rc-table-row rc-table-row-level-0" > 27 @@ -5775,7 +5775,7 @@ exports[`Table.expand renders expand icon to the specify column 1`] = ` style="padding-left:0px" /> 28 @@ -5834,7 +5834,7 @@ exports[`Table.expand renders expand row correctly 1`] = ` style="padding-left:0px" /> Lucy @@ -5855,7 +5855,7 @@ exports[`Table.expand renders expand row correctly 1`] = ` style="padding-left:0px" /> Jack @@ -5919,7 +5919,7 @@ exports[`Table.expand renders expend row class correctly 1`] = ` style="padding-left:0px" /> Lucy @@ -5952,7 +5952,7 @@ exports[`Table.expand renders expend row class correctly 1`] = ` style="padding-left:0px" /> Jack @@ -6016,7 +6016,7 @@ exports[`Table.expand renders nested data correctly 1`] = ` style="padding-left:0px" /> Lucy @@ -6037,7 +6037,7 @@ exports[`Table.expand renders nested data correctly 1`] = ` style="padding-left:15px" /> Jim @@ -6058,7 +6058,7 @@ exports[`Table.expand renders nested data correctly 1`] = ` style="padding-left:0px" /> Jack @@ -6122,7 +6122,7 @@ exports[`Table.expand renders tree row correctly 1`] = ` style="padding-left:0px" /> Lucy @@ -6143,7 +6143,7 @@ exports[`Table.expand renders tree row correctly 1`] = ` style="padding-left:15px" /> Jim @@ -6164,7 +6164,7 @@ exports[`Table.expand renders tree row correctly 1`] = ` style="padding-left:0px" /> Jack From b150cf9b0040862d2d9d8c1cae3357cb828b457b Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Wed, 18 Oct 2017 15:27:42 +0800 Subject: [PATCH 07/26] Fix expand row --- src/ExpandableTable.js | 6 +- src/ExpandedRowHeigh.js | 19 +- src/TableRow.jsx | 17 + .../Table.expandRow.spec.js.snap | 443 ++++++++++++++++++ 4 files changed, 472 insertions(+), 13 deletions(-) diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index 9974393e0..702c346d4 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -174,11 +174,9 @@ class ExpandableTable extends React.Component { renderRows = (renderRows, record, index, indent, fixed, parentKey) => { const { expandedRowClassName, columns, expandedRowRender, childrenColumnName } = this.props; const childrenData = record[childrenColumnName]; - const expanded = this.isRowExpanded(record, index); - const expandedRowContent = (expandedRowRender && expanded) ? - expandedRowRender(record, index, indent) : null; + const expandedRowContent = expandedRowRender && expandedRowRender(record, index, indent); - if (expandedRowContent && expanded) { + if (expandedRowContent) { return [ this.renderExpandedRow( parentKey, diff --git a/src/ExpandedRowHeigh.js b/src/ExpandedRowHeigh.js index 58b39e5bc..59c5094ee 100644 --- a/src/ExpandedRowHeigh.js +++ b/src/ExpandedRowHeigh.js @@ -2,18 +2,19 @@ import React from 'react'; import { connect } from 'mini-store'; class ExpandedRowHeigh extends React.Component { - componentDidMount() { - this.setHeight(); + componentDidUpdate() { + if (!this.props.fixed && this.rowRef && !this.set) { + this.setHeight(); + } } setHeight() { - const { store, fixed, rowKey } = this.props; - if (!fixed) { - const { expandedRowsHeight } = store.getState(); - const height = this.rowRef.getBoundingClientRect().height; - expandedRowsHeight[rowKey] = height; - store.setState({ expandedRowsHeight }); - } + const { store, rowKey } = this.props; + const { expandedRowsHeight } = store.getState(); + const height = this.rowRef.getBoundingClientRect().height; + expandedRowsHeight[rowKey] = height; + store.setState({ expandedRowsHeight }); + this.set = true; } saveRowRef = (node) => { diff --git a/src/TableRow.jsx b/src/TableRow.jsx index 26f3abed9..200d8575d 100644 --- a/src/TableRow.jsx +++ b/src/TableRow.jsx @@ -41,6 +41,18 @@ class TableRow extends React.Component { renderExpandIcon() {}, } + constructor(props) { + super(props); + + this.shouldRender = props.visible; + } + + componentWillReceiveProps(nextProps) { + if (this.props.visible || (!this.props.visible && nextProps.visible)) { + this.shouldRender = true; + } + } + onRowClick = (event) => { const { record, index, onRowClick } = this.props; onRowClick(record, index, event); @@ -69,6 +81,11 @@ class TableRow extends React.Component { } render() { + + if (!this.shouldRender) { + return null; + } + const { prefixCls, columns, diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index fdf6b41f8..ffef34678 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -1841,6 +1841,84 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` + + + + + + + @@ -3114,6 +3192,124 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` + + + + + + + +

+ extra data +

+ +
+ +
+
+
+
+ + + + + + + +

+ extra data +

+ +
+ +
+
+
+
+ + + + + + + @@ -5569,6 +5961,18 @@ exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` 27 + + +

+ extra data +

+ + @@ -5674,6 +6078,21 @@ exports[`Table.expand renders expand icon as cell 1`] = ` 27 + + + +

+ extra data +

+ + @@ -5759,6 +6178,18 @@ exports[`Table.expand renders expand icon to the specify column 1`] = ` 27 + + +

+ extra data +

+ + @@ -5844,6 +6275,18 @@ exports[`Table.expand renders expand row correctly 1`] = ` 27 + + +

+ extra data +

+ + From fadf5636a02559a418773b5d4561ddaa6e017846 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Wed, 18 Oct 2017 15:58:13 +0800 Subject: [PATCH 08/26] Fix parentKey --- examples/dropdown.js | 33 +++++----- examples/expandedRowRender.js | 59 ++++++++--------- package.json | 2 +- src/ExpandableTable.js | 1 - src/TableRow.jsx | 11 ++-- .../Table.expandRow.spec.js.snap | 66 +------------------ 6 files changed, 54 insertions(+), 118 deletions(-) diff --git a/examples/dropdown.js b/examples/dropdown.js index 55255ac68..d09264a22 100644 --- a/examples/dropdown.js +++ b/examples/dropdown.js @@ -18,35 +18,34 @@ for (let i = 0; i < 10; i++) { }); } -const Test = React.createClass({ - getInitialState() { - this.filters = []; - return { - visible: false, - }; - }, +class Test extends React.Component { + filters = [] + + state = { + visible: false, + } - handleVisibleChange(visible) { + handleVisibleChange = (visible) => { this.setState({ visible }); - }, + } - handleSelect(selected) { + handleSelect = (selected) => { this.filters.push(selected); - }, + } - handleDeselect(key) { + handleDeselect = (key) => { const index = this.filters.indexOf(key); if (index !== -1) { this.filters.splice(index, 1); } - }, + } - confirmFilter() { + confirmFilter = () => { console.log(this.filters.join(',')); this.setState({ visible: false, }); - }, + } render() { const menu = ( @@ -100,8 +99,8 @@ const Test = React.createClass({ rowKey={record => record.key} /> ); - }, -}); + } +} ReactDOM.render(
diff --git a/examples/expandedRowRender.js b/examples/expandedRowRender.js index aafa30e2a..043a2fdd4 100644 --- a/examples/expandedRowRender.js +++ b/examples/expandedRowRender.js @@ -10,43 +10,42 @@ const tableData = [ { key: 2, a: '1333', c: 'eee', d: 2 }, ]; -const App = React.createClass({ - getInitialState() { - this.columns = [ - { title: 'title 1', dataIndex: 'a', key: 'a', width: 100 }, - { title: 'title 2', dataIndex: 'b', key: 'b', width: 100 }, - { title: 'title 3', dataIndex: 'c', key: 'c', width: 200 }, - { title: 'Operation', dataIndex: '', key: 'x', render: this.renderAction }, - ]; - return { - data: tableData, - expandedRowKeys: [], - expandIconAsCell: true, - expandRowByClick: false, - }; - }, +class App extends React.Component { + columns = [ + { title: 'title 1', dataIndex: 'a', key: 'a', width: 100 }, + { title: 'title 2', dataIndex: 'b', key: 'b', width: 100 }, + { title: 'title 3', dataIndex: 'c', key: 'c', width: 200 }, + { title: 'Operation', dataIndex: '', key: 'x', render: this.renderAction }, + ] - onExpand(expanded, record) { + state = { + data: tableData, + expandedRowKeys: [], + expandIconAsCell: true, + expandRowByClick: false, + } + + onExpand = (expanded, record) => { console.log('onExpand', expanded, record); - }, + } - onExpandedRowsChange(rows) { + onExpandedRowsChange = (rows) => { this.setState({ expandedRowKeys: rows, }); - }, + } - onExpandIconAsCellChange(e) { + onExpandIconAsCellChange = (e) => { this.setState({ expandIconAsCell: e.target.checked, }); - }, + } - onExpandRowByClickChange(e) { + onExpandRowByClickChange = (e) => { this.setState({ expandRowByClick: e.target.checked, }); - }, + } toggleButton() { if (this.state.expandedRowKeys.length) { @@ -55,22 +54,22 @@ const App = React.createClass({ } const openAll = () => this.setState({ expandedRowKeys: [0, 1, 2] }); return ; - }, + } remove(index) { const data = this.state.data; data.splice(index, 1); this.setState({ data }); - }, + } expandedRowRender(record) { - console.log(record); + // console.log(record); return

extra: {record.a}

; - }, + } renderAction(o, row, index) { return this.remove(index)}>Delete; - }, + } render() { const { expandIconAsCell, expandRowByClick, expandedRowKeys, data } = this.state; @@ -103,8 +102,8 @@ const App = React.createClass({ />
); - }, -}); + } +} ReactDOM.render(
diff --git a/package.json b/package.json index 2b4be82ee..71857513d 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "jest": "^21.2.1", "pre-commit": "1.x", "rc-animate": "^2.3.0", - "rc-dropdown": "~1.4.10", + "rc-dropdown": "~2.0.1", "rc-menu": "^5.0.11", "rc-tools": "7.x", "react": "^16.0.0", diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index 702c346d4..bd6f96767 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -161,7 +161,6 @@ class ExpandableTable extends React.Component { parentKey={parentKey} prefixCls={`${prefixCls}-expanded-row`} indent={1} - expandable={false} fixed={!!fixed} height={height} saveRowRef={saveRowRef} diff --git a/src/TableRow.jsx b/src/TableRow.jsx index 200d8575d..826b9227f 100644 --- a/src/TableRow.jsx +++ b/src/TableRow.jsx @@ -81,7 +81,6 @@ class TableRow extends React.Component { } render() { - if (!this.shouldRender) { return null; } @@ -154,7 +153,9 @@ class TableRow extends React.Component { } } -export default connect(({ currentHoverKey, expandedRowKeys }, { rowKey, parentKey }) => ({ - hovered: currentHoverKey === rowKey, - visible: parentKey ? !!~expandedRowKeys.indexOf(parentKey) : true, -}))(TableRow); +export default connect(({ currentHoverKey, expandedRowKeys }, { rowKey, parentKey }) => { + return ({ + hovered: currentHoverKey === rowKey, + visible: typeof parentKey !== 'undefined' ? !!~expandedRowKeys.indexOf(parentKey) : true, + }) +})(TableRow); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index ffef34678..dd55a807e 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -1286,7 +1286,6 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` }, ] } - expandable={false} fixed={false} height={undefined} indent={1} @@ -1308,7 +1307,6 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } expandIconColumnIndex={0} expandRowByClick={false} - expandable={false} fixed={false} hasExpandIcon={[Function]} height={undefined} @@ -1868,7 +1866,6 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` }, ] } - expandable={false} fixed={false} height={undefined} indent={1} @@ -1890,7 +1887,6 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } expandIconColumnIndex={0} expandRowByClick={false} - expandable={false} fixed={false} hasExpandIcon={[Function]} height={undefined} @@ -3219,7 +3215,6 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` }, ] } - expandable={false} fixed={false} height={undefined} indent={1} @@ -3241,7 +3236,6 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` } expandIconColumnIndex={0} expandRowByClick={false} - expandable={false} fixed={false} hasExpandIcon={[Function]} height={undefined} @@ -3265,7 +3259,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` "subscribe": [Function], } } - visible={true} + visible={false} > - - -

- extra data -

- - @@ -6078,21 +6055,6 @@ exports[`Table.expand renders expand icon as cell 1`] = ` 27 - - - -

- extra data -

- - @@ -6178,18 +6140,6 @@ exports[`Table.expand renders expand icon to the specify column 1`] = ` 27 - - -

- extra data -

- - @@ -6275,18 +6225,6 @@ exports[`Table.expand renders expand row correctly 1`] = ` 27 - - -

- extra data -

- - From 1ce0b1e8fe836cbcdf15fca9bfd55db2f0b211bd Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Wed, 18 Oct 2017 16:25:00 +0800 Subject: [PATCH 09/26] Fix fixed columns --- examples/fixedColumns-auto-height.js | 18 +++++++++--------- src/BaseTable.js | 5 +++-- src/ExpandableRow.js | 19 ++++++++----------- src/ExpandableTable.js | 20 +++++++++++++++++--- src/TableHeader.jsx | 13 +++---------- src/TableRow.jsx | 7 +++---- 6 files changed, 43 insertions(+), 39 deletions(-) diff --git a/examples/fixedColumns-auto-height.js b/examples/fixedColumns-auto-height.js index 791e92d20..5a2973333 100644 --- a/examples/fixedColumns-auto-height.js +++ b/examples/fixedColumns-auto-height.js @@ -21,15 +21,15 @@ const columns = [ ]; const data = [ - { a: '123', b: 'xxxxxxxx', d: 3, key: '1' }, - { a: 'cdd', b: 'edd12221', d: 3, key: '2' }, - { a: '133', c: 'edd12221', d: 2, key: '3' }, - { a: '133', c: 'edd12221', d: 2, key: '4' }, - { a: '133', c: 'edd12221', d: 2, key: '5' }, - { a: '133', c: 'edd12221', d: 2, key: '6' }, - { a: '133', c: 'edd12221', d: 2, key: '7' }, - { a: '133', c: 'edd12221', d: 2, key: '8' }, - { a: '133', c: 'edd12221', d: 2, key: '9' }, + { a: '123', b: 'xxxxxxxx', d: 3, key: '1', title: 'hello' }, + { a: 'cdd', b: 'edd12221', d: 3, key: '2', title: 'hello' }, + { a: '133', c: 'edd12221', d: 2, key: '3', title: 'hello' }, + { a: '133', c: 'edd12221', d: 2, key: '4', title: 'hello' }, + { a: '133', c: 'edd12221', d: 2, key: '5', title: 'hello' }, + { a: '133', c: 'edd12221', d: 2, key: '6', title: 'hello' }, + { a: '133', c: 'edd12221', d: 2, key: '7', title: 'hello' }, + { a: '133', c: 'edd12221', d: 2, key: '8', title: 'hello' }, + { a: '133', c: 'edd12221', d: 2, key: '9', title: 'hello' }, ]; ReactDOM.render( diff --git a/src/BaseTable.js b/src/BaseTable.js index 94d918df2..6967a5360 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -79,6 +79,7 @@ class BaseTable extends React.Component { const row = ( - {hasHead && } + {hasHead && } {hasBody && getBodyWrapper( {this.renderRows(data, 0)} diff --git a/src/ExpandableRow.js b/src/ExpandableRow.js index 1fc2258e6..e2eaaa53e 100644 --- a/src/ExpandableRow.js +++ b/src/ExpandableRow.js @@ -7,12 +7,6 @@ class ExpandableRow extends React.Component { this.handleDestroy(); } - addExpandIconCell = (cells) => { - if (this.expandIconAsCell) { - cells.push(this.renderExpandIconCell()); - } - } - hasExpandIcon = (columnIndex) => { const { expandRowByClick } = this.props; return !this.expandIconAsCell && !expandRowByClick && columnIndex === this.expandIconColumnIndex; @@ -55,10 +49,13 @@ class ExpandableRow extends React.Component { ); } - renderExpandIconCell = () => { + renderExpandIconCell = (cells) => { + if (!this.expandIconAsCell) { + return; + } const { prefixCls } = this.props; - return ( + cells.push( { + const { prefixCls, expandIconAsCell } = this.props; + if (!expandIconAsCell || fixed == 'right') { + return; + } + + rows[0].unshift({ + key: 'rc-table-expandIconAsCell', + className: `${prefixCls}-expand-icon-th`, + title: '', + rowSpan: rows.length, + }); + } + renderExpandedRow(parentKey, content, className, fixed) { const { prefixCls, expandIconAsCell } = this.props; let colCount; @@ -151,7 +165,7 @@ class ExpandableTable extends React.Component { {({ height, saveRowRef }) => ( @@ -203,9 +216,10 @@ class ExpandableTable extends React.Component { return children({ props: this.props, - renderRows: this.renderRows, needIndentSpaced, + renderRows: this.renderRows, handleExpandChange: this.handleExpandChange, + renderExpandIndentCell: this.renderExpandIndentCell, }); } } diff --git a/src/TableHeader.jsx b/src/TableHeader.jsx index e42983217..550845389 100644 --- a/src/TableHeader.jsx +++ b/src/TableHeader.jsx @@ -45,8 +45,8 @@ function getHeaderRowStyle(columns, rows, fixedColumnsHeadRowsHeight) { export default function TableHeader(props, { table }) { const { fixedColumnsHeadRowsHeight } = table.state; - const { prefixCls, showHeader, expandIconAsCell } = table.props; - const { columns, fixed } = props; + const { prefixCls, showHeader } = table.props; + const { expander, columns, fixed } = props; if (!showHeader) { return null; @@ -54,14 +54,7 @@ export default function TableHeader(props, { table }) { const rows = getHeaderRows(columns); - if (expandIconAsCell && fixed !== 'right') { - rows[0].unshift({ - key: 'rc-table-expandIconAsCell', - className: `${prefixCls}-expand-icon-th`, - title: '', - rowSpan: rows.length, - }); - } + expander.renderExpandIndentCell(rows, fixed); const trStyle = fixed ? getHeaderRowStyle(columns, rows, fixedColumnsHeadRowsHeight) : null; diff --git a/src/TableRow.jsx b/src/TableRow.jsx index 826b9227f..164cf4a1b 100644 --- a/src/TableRow.jsx +++ b/src/TableRow.jsx @@ -24,7 +24,6 @@ class TableRow extends React.Component { indent: PropTypes.number, indentSize: PropTypes.number, expandedRow: PropTypes.bool, - fixed: PropTypes.bool, } static defaultProps = { @@ -36,9 +35,9 @@ class TableRow extends React.Component { expandIconColumnIndex: 0, expandRowByClick: false, onHover() {}, - addExpandIconCell() {}, hasExpandIcon() {}, renderExpandIcon() {}, + renderExpandIconCell() {}, } constructor(props) { @@ -99,7 +98,7 @@ class TableRow extends React.Component { hasExpandIcon, addExpandIconCell, renderExpandIcon, - renderExpandIconCell, + renderExpandIconCell } = this.props; let { className } = this.props; @@ -110,7 +109,7 @@ class TableRow extends React.Component { const cells = []; - addExpandIconCell(cells); + renderExpandIconCell(cells); for (let i = 0; i < columns.length; i++) { cells.push( From 5c7c73d5f7f9af3a6cc416ee5f99901449ad92e4 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Wed, 18 Oct 2017 17:13:23 +0800 Subject: [PATCH 10/26] Fix examples --- examples/fixedColumnsAndHeader.js | 2 +- examples/key.js | 49 +++++++++++++------------------ src/HeadTable.js | 3 +- src/Table.jsx | 1 + 4 files changed, 25 insertions(+), 30 deletions(-) diff --git a/examples/fixedColumnsAndHeader.js b/examples/fixedColumnsAndHeader.js index 88a8832d1..18f9c8a23 100644 --- a/examples/fixedColumnsAndHeader.js +++ b/examples/fixedColumnsAndHeader.js @@ -34,6 +34,6 @@ const data = [ ReactDOM.render(

Fixed columns and header

- +
, document.getElementById('__react-content')); diff --git a/examples/key.js b/examples/key.js index dcec2c6b7..4f36cef5b 100644 --- a/examples/key.js +++ b/examples/key.js @@ -4,25 +4,21 @@ import ReactDOM from 'react-dom'; import Table from 'rc-table'; import 'rc-table/assets/index.less'; -const CheckBox = React.createClass({ - render() { - const props = this.props; - return ( - - ); - }, -}); +const CheckBox = ({ id }) => ( + +); + +class MyTable extends React.Component { + constructor(props) { + super(props); -const MyTable = React.createClass({ - getInitialState() { - const props = this.props; - return { + this.state = { data: props.data, }; - }, + } remove(index) { const rows = this.state.data; @@ -30,22 +26,19 @@ const MyTable = React.createClass({ this.setState({ data: rows, }); - }, + } - handleClick(index) { - const self = this; - return () => { - self.remove(index); - }; - }, + handleClick = (index) => () => { + this.remove(index); + } checkbox(a) { return ; - }, + } - renderAction(o, row, index) { + renderAction = (o, row, index) => { return Delete; - }, + } render() { const state = this.state; @@ -58,8 +51,8 @@ const MyTable = React.createClass({ return (
record.a} /> ); - }, -}); + } +} const data = [{ a: '123' }, { a: 'cdd', b: 'edd' }, { a: '1333', c: 'eee', d: 2 }]; diff --git a/src/HeadTable.js b/src/HeadTable.js index 7aff1a43b..522dfe1bc 100644 --- a/src/HeadTable.js +++ b/src/HeadTable.js @@ -5,7 +5,7 @@ import BaseTable from './BaseTable'; export default function HeadTable(props, { table }) { const { prefixCls, scroll, showHeader } = table.props; - const { columns, fixed, tableClassName, handleBodyScrollLeft } = props; + const { columns, fixed, tableClassName, handleBodyScrollLeft, expander } = props; const { saveRef } = table; let { useFixedHeader } = table.props; const headStyle = {}; @@ -38,6 +38,7 @@ export default function HeadTable(props, { table }) { hasBody={false} fixed={fixed} columns={columns} + expander={expander} /> ); diff --git a/src/Table.jsx b/src/Table.jsx index 43acf2d08..a9ccfe7bb 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -321,6 +321,7 @@ export default class Table extends React.Component { fixed={fixed} tableClassName={tableClassName} handleBodyScrollLeft={this.handleBodyScrollLeft} + expander={this.expander} /> ); From 0bb96e7629d33d1fec8221353052bca6511165df Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Thu, 19 Oct 2017 22:14:55 +0800 Subject: [PATCH 11/26] Fix visible logic --- src/BaseTable.js | 14 +- src/ExpandableTable.js | 15 +- src/TableRow.jsx | 4 +- .../Table.expandRow.spec.js.snap | 893 +++++++++++++++--- .../Table.fixedColumns.spec.js.snap | 57 +- 5 files changed, 811 insertions(+), 172 deletions(-) diff --git a/src/BaseTable.js b/src/BaseTable.js index 6967a5360..dd2e45dd5 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -25,7 +25,7 @@ class BaseTable extends React.Component { }); } - renderRows = (renderData, indent, parentKey) => { + renderRows = (renderData, indent, ancestorKeys = []) => { const { table } = this.context; const { fixedColumnsBodyRowsHeight } = table.state; const { @@ -85,7 +85,6 @@ class BaseTable extends React.Component { record={record} key={key} rowKey={key} - parentKey={key} onRowClick={onRowClick} needIndentSpaced={expander.needIndentSpaced} onExpandedChange={expander.handleExpandChange} @@ -107,6 +106,7 @@ class BaseTable extends React.Component { {...onHoverProps} hoverKey={key} rowKey={key} + ancestorKeys={ancestorKeys} ref={rowRef(record, i, indent)} {...expandableRow} /> @@ -116,7 +116,15 @@ class BaseTable extends React.Component { rows.push(row); - const expandedRows = expander.renderRows(this.renderRows, record, i, indent, fixed, key); + const expandedRows = expander.renderRows( + this.renderRows, + record, + i, + indent, + fixed, + key, + ancestorKeys + ); if (expandedRows) { rows.push(...expandedRows); diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index 2009f9aff..32de32e5e 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -133,7 +133,7 @@ class ExpandableTable extends React.Component { }); } - renderExpandedRow(parentKey, content, className, fixed) { + renderExpandedRow(content, className, ancestorKeys, fixed) { const { prefixCls, expandIconAsCell } = this.props; let colCount; if (fixed === 'left') { @@ -159,7 +159,7 @@ class ExpandableTable extends React.Component { }); } - const rowKey = `${parentKey}-extra-row`; + const rowKey = `${ancestorKeys[0]}-extra-row`; return ( { + renderRows = (renderRows, record, index, indent, fixed, parentKey, ancestorKeys) => { const { expandedRowClassName, columns, expandedRowRender, childrenColumnName } = this.props; const childrenData = record[childrenColumnName]; const expandedRowContent = expandedRowRender && expandedRowRender(record, index, indent); + const nextAncestorKeys = [...ancestorKeys, parentKey]; if (expandedRowContent) { return [ this.renderExpandedRow( - parentKey, expandedRowContent, expandedRowClassName(record, index, indent), + nextAncestorKeys, fixed, ) ]; @@ -203,9 +204,7 @@ class ExpandableTable extends React.Component { return renderRows( childrenData, indent + 1, - columns, - fixed, - parentKey, + nextAncestorKeys, ); } } diff --git a/src/TableRow.jsx b/src/TableRow.jsx index 164cf4a1b..43c7fb7dc 100644 --- a/src/TableRow.jsx +++ b/src/TableRow.jsx @@ -152,9 +152,9 @@ class TableRow extends React.Component { } } -export default connect(({ currentHoverKey, expandedRowKeys }, { rowKey, parentKey }) => { +export default connect(({ currentHoverKey, expandedRowKeys }, { rowKey, ancestorKeys }) => { return ({ hovered: currentHoverKey === rowKey, - visible: typeof parentKey !== 'undefined' ? !!~expandedRowKeys.indexOf(parentKey) : true, + visible: ancestorKeys.length === 0 || ancestorKeys.every(k => ~expandedRowKeys.indexOf(k)), }) })(TableRow); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index dd55a807e..abbd73ff4 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -296,6 +296,119 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` }, ] } + expander={ + Object { + "handleExpandChange": [Function], + "needIndentSpaced": false, + "props": Object { + "bodyStyle": Object {}, + "children": [Function], + "childrenColumnName": "children", + "columnManager": ColumnManager { + "_cached": Object { + "groupedColumns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + "isAnyColumnsFixed": false, + "isAnyColumnsLeftFixed": false, + "isAnyColumnsRightFixed": false, + "leafColumns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + }, + "columns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + }, + "columns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + "data": Array [ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + }, + Object { + "age": 28, + "key": 1, + "name": "Jack", + }, + ], + "defaultExpandAllRows": false, + "defaultExpandedRowKeys": Array [], + "emptyText": [Function], + "expandIconAsCell": false, + "expandIconColumnIndex": 0, + "expandedRowClassName": [Function], + "expandedRowKeys": Array [ + 0, + ], + "expandedRowRender": [Function], + "getBodyWrapper": [Function], + "getRowKey": [Function], + "indentSize": 15, + "onExpand": [Function], + "onExpandedRowsChange": [Function], + "onRowClick": [Function], + "onRowContextMenu": [Function], + "onRowDoubleClick": [Function], + "onRowMouseEnter": [Function], + "onRowMouseLeave": [Function], + "prefixCls": "rc-table", + "rowClassName": [Function], + "rowKey": "key", + "rowRef": [Function], + "scroll": Object {}, + "showHeader": true, + "store": Object { + "getState": [Function], + "setState": [Function], + "subscribe": [Function], + }, + "style": Object {}, + "useFixedHeader": false, + }, + "renderExpandIndentCell": [Function], + "renderRows": [Function], + } + } fixed={undefined} handleBodyScrollLeft={[Function]} key="head" @@ -425,6 +538,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` "style": Object {}, "useFixedHeader": false, }, + "renderExpandIndentCell": [Function], "renderRows": [Function], } } @@ -563,6 +677,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` "style": Object {}, "useFixedHeader": false, }, + "renderExpandIndentCell": [Function], "renderRows": [Function], } } @@ -695,6 +810,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` "style": Object {}, "useFixedHeader": false, }, + "renderExpandIndentCell": [Function], "renderRows": [Function], } } @@ -768,6 +884,119 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` }, ] } + expander={ + Object { + "handleExpandChange": [Function], + "needIndentSpaced": false, + "props": Object { + "bodyStyle": Object {}, + "children": [Function], + "childrenColumnName": "children", + "columnManager": ColumnManager { + "_cached": Object { + "groupedColumns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + "isAnyColumnsFixed": false, + "isAnyColumnsLeftFixed": false, + "isAnyColumnsRightFixed": false, + "leafColumns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + }, + "columns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + }, + "columns": Array [ + Object { + "dataIndex": "name", + "key": "name", + "title": "Name", + }, + Object { + "dataIndex": "age", + "key": "age", + "title": "Age", + }, + ], + "data": Array [ + Object { + "age": 27, + "key": 0, + "name": "Lucy", + }, + Object { + "age": 28, + "key": 1, + "name": "Jack", + }, + ], + "defaultExpandAllRows": false, + "defaultExpandedRowKeys": Array [], + "emptyText": [Function], + "expandIconAsCell": false, + "expandIconColumnIndex": 0, + "expandedRowClassName": [Function], + "expandedRowKeys": Array [ + 0, + ], + "expandedRowRender": [Function], + "getBodyWrapper": [Function], + "getRowKey": [Function], + "indentSize": 15, + "onExpand": [Function], + "onExpandedRowsChange": [Function], + "onRowClick": [Function], + "onRowContextMenu": [Function], + "onRowDoubleClick": [Function], + "onRowMouseEnter": [Function], + "onRowMouseLeave": [Function], + "prefixCls": "rc-table", + "rowClassName": [Function], + "rowKey": "key", + "rowRef": [Function], + "scroll": Object {}, + "showHeader": true, + "store": Object { + "getState": [Function], + "setState": [Function], + "subscribe": [Function], + }, + "style": Object {}, + "useFixedHeader": false, + }, + "renderExpandIndentCell": [Function], + "renderRows": [Function], + } + } fixed={undefined} > @@ -2812,6 +3282,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` ] } expandedRowRender={[Function]} + fixed={undefined} getBodyWrapper={[Function]} getRowKey={[Function]} indentSize={15} @@ -2826,7 +3297,6 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` onRowDoubleClick={[Function]} onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} - parentKey={0} prefixCls="rc-table-row" record={ Object { @@ -2939,6 +3409,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` ] } expandedRowRender={[Function]} + fixed={undefined} getBodyWrapper={[Function]} getRowKey={[Function]} indentSize={15} @@ -2952,7 +3423,6 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` onRowDoubleClick={[Function]} onRowMouseEnter={[Function]} onRowMouseLeave={[Function]} - parentKey={0} prefixCls="rc-table-row" record={ Object { @@ -2977,7 +3447,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` useFixedHeader={false} > - - - - @@ -6513,27 +7209,6 @@ exports[`Table.expand renders tree row correctly 1`] = ` 27 - - - - diff --git a/tests/__snapshots__/Table.fixedColumns.spec.js.snap b/tests/__snapshots__/Table.fixedColumns.spec.js.snap index dbd161a3e..c6ce2ec65 100644 --- a/tests/__snapshots__/Table.fixedColumns.spec.js.snap +++ b/tests/__snapshots__/Table.fixedColumns.spec.js.snap @@ -810,10 +810,6 @@ exports[`Table.fixedColumns renders correctly 1`] = ` @@ -823,10 +819,6 @@ exports[`Table.fixedColumns renders correctly 1`] = ` @@ -835,84 +827,49 @@ exports[`Table.fixedColumns renders correctly 1`] = ` > + /> + /> + /> + /> + /> + /> + />
- - - Jim - - 2 -
- - - Jim - - 1 -
- xxxxxxxx
- edd12221
- -
- -
- -
- -
- -
- -
- -
From ece046fb1a81e76ae6c242fe99e88a7c9e05eae5 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Thu, 19 Oct 2017 22:21:25 +0800 Subject: [PATCH 12/26] Use es6 class --- examples/scrollY.js | 20 +++++++++----------- examples/subTable.js | 13 +++++++------ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/examples/scrollY.js b/examples/scrollY.js index 90848ee93..ae286c5ed 100644 --- a/examples/scrollY.js +++ b/examples/scrollY.js @@ -14,18 +14,16 @@ for (let i = 0; i < 10; i++) { }); } -const Test = React.createClass({ - getInitialState() { - return { - showBody: true, - }; - }, +class Demo extends React.Component { + state = { + showBody: true, + } - toggleBody() { + toggleBody = () => { this.setState({ showBody: !this.state.showBody, }); - }, + } render() { const columns = [ @@ -52,13 +50,13 @@ const Test = React.createClass({ }} /> ); - }, -}); + } +} ReactDOM.render(

scroll body table

- +
, document.getElementById('__react-content') ); diff --git a/examples/subTable.js b/examples/subTable.js index 107d05304..459428e36 100644 --- a/examples/subTable.js +++ b/examples/subTable.js @@ -29,11 +29,12 @@ const data = [ }, ]; -const MyTable = React.createClass({ - handleClick(record, e) { +class Demo extends React.Component { + handleClick = (record, e) => { e.preventDefault(); console.log(record.a); - }, + } + render() { const columns = [ { title: 'title1', dataIndex: 'a', key: 'a', width: 100 }, @@ -56,7 +57,7 @@ const MyTable = React.createClass({ />
); - }, -}); + } +} -ReactDOM.render(, document.getElementById('__react-content')); +ReactDOM.render(, document.getElementById('__react-content')); From f3e25e839b0d4a6a220426a6cf55c67c9eff6814 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Fri, 20 Oct 2017 09:45:02 +0800 Subject: [PATCH 13/26] Rename to js --- src/{Column.jsx => Column.js} | 0 src/{ColumnGroup.jsx => ColumnGroup.js} | 0 src/{ExpandIcon.jsx => ExpandIcon.js} | 0 src/{Table.jsx => Table.js} | 2 +- src/{TableCell.jsx => TableCell.js} | 0 src/{TableHeader.jsx => TableHeader.js} | 0 src/{TableRow.jsx => TableRow.js} | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename src/{Column.jsx => Column.js} (100%) rename src/{ColumnGroup.jsx => ColumnGroup.js} (100%) rename src/{ExpandIcon.jsx => ExpandIcon.js} (100%) rename src/{Table.jsx => Table.js} (99%) rename src/{TableCell.jsx => TableCell.js} (100%) rename src/{TableHeader.jsx => TableHeader.js} (100%) rename src/{TableRow.jsx => TableRow.js} (100%) diff --git a/src/Column.jsx b/src/Column.js similarity index 100% rename from src/Column.jsx rename to src/Column.js diff --git a/src/ColumnGroup.jsx b/src/ColumnGroup.js similarity index 100% rename from src/ColumnGroup.jsx rename to src/ColumnGroup.js diff --git a/src/ExpandIcon.jsx b/src/ExpandIcon.js similarity index 100% rename from src/ExpandIcon.jsx rename to src/ExpandIcon.js diff --git a/src/Table.jsx b/src/Table.js similarity index 99% rename from src/Table.jsx rename to src/Table.js index a9ccfe7bb..abac6735b 100644 --- a/src/Table.jsx +++ b/src/Table.js @@ -33,6 +33,7 @@ export default class Table extends React.Component { rowRef: PropTypes.func, getBodyWrapper: PropTypes.func, children: PropTypes.node, + ...ExpandableTable.PropTypes, } static childContextTypes = { @@ -71,7 +72,6 @@ export default class Table extends React.Component { this.setScrollPosition('left'); this.state = { - currentHoverKey: null, fixedColumnsHeadRowsHeight: [], fixedColumnsBodyRowsHeight: [], }; diff --git a/src/TableCell.jsx b/src/TableCell.js similarity index 100% rename from src/TableCell.jsx rename to src/TableCell.js diff --git a/src/TableHeader.jsx b/src/TableHeader.js similarity index 100% rename from src/TableHeader.jsx rename to src/TableHeader.js diff --git a/src/TableRow.jsx b/src/TableRow.js similarity index 100% rename from src/TableRow.jsx rename to src/TableRow.js From 049d0317de3e4d1fddaf50fa28bd5525c5521e7d Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Fri, 20 Oct 2017 11:50:52 +0800 Subject: [PATCH 14/26] Store row height in store --- src/BaseTable.js | 52 +- src/ExpandedRowHeigh.js | 29 +- src/Table.js | 14 +- src/TableHeader.js | 25 +- src/TableHeaderRow.js | 32 ++ .../Table.expandRow.spec.js.snap | 444 +++++++++++++++--- 6 files changed, 478 insertions(+), 118 deletions(-) create mode 100644 src/TableHeaderRow.js diff --git a/src/BaseTable.js b/src/BaseTable.js index dd2e45dd5..d98754df5 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -5,6 +5,7 @@ import ColGroup from './ColGroup'; import TableHeader from './TableHeader'; import TableRow from './TableRow'; import ExpandableRow from './ExpandableRow'; +import ExpandedRowHeigh from './ExpandedRowHeigh'; class BaseTable extends React.Component { static propTypes = { @@ -27,7 +28,6 @@ class BaseTable extends React.Component { renderRows = (renderData, indent, ancestorKeys = []) => { const { table } = this.context; - const { fixedColumnsBodyRowsHeight } = table.state; const { columnManager, getRowKey, @@ -62,9 +62,6 @@ class BaseTable extends React.Component { onHoverProps.onHover = this.handleRowHover; } - const height = (fixed && fixedColumnsBodyRowsHeight[i]) ? - fixedColumnsBodyRowsHeight[i] : null; - let leafColumns; if (fixed === 'left') { leafColumns = columnManager.leftLeafColumns(); @@ -90,26 +87,35 @@ class BaseTable extends React.Component { onExpandedChange={expander.handleExpandChange} > {( expandableRow ) => ( - + fixed={fixed} + index={i} + > + {({ height }) => ( + + )} +
)}
); diff --git a/src/ExpandedRowHeigh.js b/src/ExpandedRowHeigh.js index 59c5094ee..2255d598f 100644 --- a/src/ExpandedRowHeigh.js +++ b/src/ExpandedRowHeigh.js @@ -24,15 +24,34 @@ class ExpandedRowHeigh extends React.Component { render() { const { children, height } = this.props; return children({ - heigh: height, + height, saveRowRef: this.saveRowRef, }); } } -export default connect(({ expandedRowsHeight }, { fixed, height, rowKey }) => { - if (fixed && expandedRowsHeight[rowKey]) { - return { height: expandedRowsHeight[rowKey] } +function getRowHeight(state, props) { + const { expandedRowsHeight, fixedColumnsBodyRowsHeight } = state; + const { fixed, index, rowKey } = props; + + if (!fixed) { + return null; } - return { height }; + + + if (expandedRowsHeight[rowKey]) { + return expandedRowsHeight[rowKey]; + } + + if (fixedColumnsBodyRowsHeight[index]) { + return fixedColumnsBodyRowsHeight[index]; + } + + return null; +} + +export default connect((state, props) => { + return { + height: getRowHeight(state, props), + }; })(ExpandedRowHeigh) diff --git a/src/Table.js b/src/Table.js index abac6735b..b0f57ceb2 100644 --- a/src/Table.js +++ b/src/Table.js @@ -67,14 +67,12 @@ export default class Table extends React.Component { this.store = create({ currentHoverKey: null, + fixedColumnsHeadRowsHeight: [], + fixedColumnsBodyRowsHeight: [], }); this.setScrollPosition('left'); - this.state = { - fixedColumnsHeadRowsHeight: [], - fixedColumnsBodyRowsHeight: [], - }; this.debouncedWindowResize = debounce(this.handleWindowResize, 150); } @@ -204,11 +202,13 @@ export default class Table extends React.Component { const fixedColumnsBodyRowsHeight = [].map.call( bodyRows, row => row.getBoundingClientRect().height || 'auto' ); - if (shallowequal(this.state.fixedColumnsHeadRowsHeight, fixedColumnsHeadRowsHeight) && - shallowequal(this.state.fixedColumnsBodyRowsHeight, fixedColumnsBodyRowsHeight)) { + const state = this.store.getState(); + if (shallowequal(state.fixedColumnsHeadRowsHeight, fixedColumnsHeadRowsHeight) && + shallowequal(state.fixedColumnsBodyRowsHeight, fixedColumnsBodyRowsHeight)) { return; } - this.setState({ + + this.store.setState({ fixedColumnsHeadRowsHeight, fixedColumnsBodyRowsHeight, }); diff --git a/src/TableHeader.js b/src/TableHeader.js index 550845389..3d555b1f3 100644 --- a/src/TableHeader.js +++ b/src/TableHeader.js @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import TableHeaderRow from './TableHeaderRow'; function getHeaderRows(columns, currentRow = 0, rows) { rows = rows || []; @@ -32,19 +33,7 @@ function getHeaderRows(columns, currentRow = 0, rows) { return rows.filter(row => row.length > 0); } -function getHeaderRowStyle(columns, rows, fixedColumnsHeadRowsHeight) { - const headerHeight = fixedColumnsHeadRowsHeight[0]; - if (headerHeight && columns) { - if (headerHeight === 'auto') { - return { height: 'auto' }; - } - return { height: headerHeight / rows.length }; - } - return null; -} - export default function TableHeader(props, { table }) { - const { fixedColumnsHeadRowsHeight } = table.state; const { prefixCls, showHeader } = table.props; const { expander, columns, fixed } = props; @@ -56,15 +45,17 @@ export default function TableHeader(props, { table }) { expander.renderExpandIndentCell(rows, fixed); - const trStyle = fixed ? getHeaderRowStyle(columns, rows, fixedColumnsHeadRowsHeight) : null; - return ( { rows.map((row, index) => ( - - {row.map((cellProps, i) => )} - + )) } diff --git a/src/TableHeaderRow.js b/src/TableHeaderRow.js new file mode 100644 index 000000000..42a8b129c --- /dev/null +++ b/src/TableHeaderRow.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { connect } from 'mini-store'; + +function TableHeaderRow({ row, height }) { + const style = { height }; + + return ( + + {row.map((cell, i) => )} + + ); +} + +function getRowHeight(state, props) { + const { fixedColumnsHeadRowsHeight } = state; + const { fixed, columns, rows } = props; + const headerHeight = fixedColumnsHeadRowsHeight[0]; + + if (headerHeight && columns) { + if (headerHeight === 'auto') { + return 'auto'; + } + return headerHeight / rows.length; + } + return null; +} + +export default connect((state, props) => { + return { + height: getRowHeight(state, props), + } +})(TableHeaderRow); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index abbd73ff4..bdf266263 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -1002,23 +1002,131 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` - - - Name - - - Age - - + + + Name + + + Age + + + + @@ -1495,7 +1601,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` > @@ -2081,7 +2185,7 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` > - - - Name - - - Age - - + + + Name + + + Age + + + + @@ -3665,7 +3875,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` > @@ -4252,7 +4460,7 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` > - - - Name - - - Age - - + + + Name + + + Age + + + + @@ -5945,7 +6259,7 @@ exports[`Table.expand expand row by click 1`] = ` > @@ -6521,7 +6833,7 @@ exports[`Table.expand expand row by click 1`] = ` > Date: Fri, 20 Oct 2017 12:36:30 +0800 Subject: [PATCH 15/26] Clean table render --- src/Table.js | 46 +- .../Table.expandRow.spec.js.snap | 2136 +++++++++-------- 2 files changed, 1169 insertions(+), 1013 deletions(-) diff --git a/src/Table.js b/src/Table.js index b0f57ceb2..b0313414a 100644 --- a/src/Table.js +++ b/src/Table.js @@ -296,17 +296,29 @@ export default class Table extends React.Component { } renderLeftFixedTable() { - return this.renderTable({ - columns: this.columnManager.leftColumns(), - fixed: 'left', - }); + const { prefixCls } = this.props; + + return ( +
+ {this.renderTable({ + columns: this.columnManager.leftColumns(), + fixed: 'left', + })} +
+ ); } renderRightFixedTable() { - return this.renderTable({ - columns: this.columnManager.rightColumns(), - fixed: 'right', - }); + const { prefixCls } = this.props; + + return ( +
+ {this.renderTable({ + columns: this.columnManager.rightColumns(), + fixed: 'right', + })} +
+ ); } renderTable(options) { @@ -386,6 +398,8 @@ export default class Table extends React.Component { } else { className += ` ${prefixCls}-scroll-position-${this.scrollPosition}`; } + const hasLeftFixed = this.columnManager.isAnyColumnsLeftFixed(); + const hasRightFixed = this.columnManager.isAnyColumnsRightFixed(); return ( @@ -397,18 +411,16 @@ export default class Table extends React.Component { {(expander) => { this.expander = expander; return ( -
+
{this.renderTitle()}
{this.renderMainTable()} - {this.columnManager.isAnyColumnsLeftFixed() && -
- {this.renderLeftFixedTable()} -
} - {this.columnManager.isAnyColumnsRightFixed() && -
- {this.renderRightFixedTable()} -
} + {hasLeftFixed && this.renderLeftFixedTable()} + {hasRightFixed && this.renderRightFixedTable()}
); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index bdf266263..5937625fd 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -1384,88 +1384,15 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` style={Object {}} useFixedHeader={false} > - - - - + } + renderExpandIcon={[Function]} + renderExpandIconCell={[Function]} + rowKey={0} + > + - - - + } + indent={0} + indentSize={15} + index={0} + key="name" prefixCls="rc-table-row" record={ Object { @@ -1552,46 +1548,74 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } } > - - - Lucy - - - - - 27 - - - - - + > + + + + + Lucy + + + + + 27 + + + + + + + @@ -1968,88 +1992,15 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` style={Object {}} useFixedHeader={false} > - - - - + } + renderExpandIcon={[Function]} + renderExpandIconCell={[Function]} + rowKey={1} + > + - - - + } + indent={0} + indentSize={15} + index={1} + key="name" prefixCls="rc-table-row" record={ Object { @@ -2136,46 +2156,74 @@ exports[`Table.expand controlled by expandedRowKeys 1`] = ` } } > - - - Jack - - - - - 28 - - - - - + > + + + + + Jack + + + + + 28 + + + + + + + - - + + - - + } + renderExpandIcon={[Function]} + renderExpandIconCell={[Function]} + rowKey={0} + > + - - - + } + indent={0} + indentSize={15} + index={0} + key="name" prefixCls="rc-table-row" record={ Object { @@ -3826,46 +3870,74 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` } } > - - - Lucy - - - - - 27 - - - - - + > + + + + + Lucy + + + + + 27 + + + + + + + @@ -4243,88 +4315,15 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` style={Object {}} useFixedHeader={false} > - - - - + } + renderExpandIcon={[Function]} + renderExpandIconCell={[Function]} + rowKey={1} + > + - - - + } + indent={0} + indentSize={15} + index={1} + key="name" prefixCls="rc-table-row" record={ Object { @@ -4411,46 +4479,74 @@ exports[`Table.expand controlled by expandedRowKeys 2`] = ` } } > - - - Jack - - - - - 28 - - - - - + > + + + + + Jack + + + + + 28 + + + + + + + @@ -6042,88 +6138,15 @@ exports[`Table.expand expand row by click 1`] = ` style={Object {}} useFixedHeader={false} > - - - - + } + renderExpandIcon={[Function]} + renderExpandIconCell={[Function]} + rowKey={0} + > + - - - + } + indent={0} + indentSize={15} + index={0} + key="name" prefixCls="rc-table-row" record={ Object { @@ -6210,46 +6302,74 @@ exports[`Table.expand expand row by click 1`] = ` } } > - - - Lucy - - - - - 27 - - - - - + > + + + + + Lucy + + + + + 27 + + + + + + + @@ -6616,88 +6736,15 @@ exports[`Table.expand expand row by click 1`] = ` style={Object {}} useFixedHeader={false} > - - - - + } + renderExpandIcon={[Function]} + renderExpandIconCell={[Function]} + rowKey={1} + > + - - - + } + indent={0} + indentSize={15} + index={1} + key="name" prefixCls="rc-table-row" record={ Object { @@ -6784,46 +6900,74 @@ exports[`Table.expand expand row by click 1`] = ` } } > - - - Jack - - - - - 28 - - - - - + > + + + + + Jack + + + + + 28 + + + + + + + Date: Fri, 20 Oct 2017 12:38:46 +0800 Subject: [PATCH 16/26] Dont need table.state in context --- src/Table.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Table.js b/src/Table.js index b0313414a..57bdbb7af 100644 --- a/src/Table.js +++ b/src/Table.js @@ -80,7 +80,6 @@ export default class Table extends React.Component { return { table: { props: this.props, - state: this.state, columnManager: this.columnManager, saveRef: this.saveRef, getRowKey: this.getRowKey, From 67fba30b6a182e277ec706d69217acbfebbcede9 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Fri, 20 Oct 2017 16:39:42 +0800 Subject: [PATCH 17/26] Clean up getRowKey --- src/BaseTable.js | 3 +- src/BodyTable.js | 3 +- src/ExpandableRow.js | 12 ++--- src/ExpandableTable.js | 43 +++++---------- src/Table.js | 2 +- tests/Table.expandRow.spec.js | 2 +- .../Table.expandRow.spec.js.snap | 53 +++++++++++++++---- 7 files changed, 66 insertions(+), 52 deletions(-) diff --git a/src/BaseTable.js b/src/BaseTable.js index d98754df5..101779d6a 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -30,7 +30,6 @@ class BaseTable extends React.Component { const { table } = this.context; const { columnManager, - getRowKey, onExpanded, } = table; const { @@ -45,7 +44,7 @@ class BaseTable extends React.Component { onRowMouseEnter, onRowMouseLeave, } = table.props; - const { columns, fixed, expander } = this.props; + const { getRowKey, columns, fixed, expander } = this.props; let rows = []; diff --git a/src/BodyTable.js b/src/BodyTable.js index 8a84b8623..6e0c29c6c 100644 --- a/src/BodyTable.js +++ b/src/BodyTable.js @@ -5,7 +5,7 @@ import BaseTable from './BaseTable'; export default function BodyTable(props, { table }) { const { prefixCls, scroll } = table.props; - const { columns, fixed, tableClassName, handleBodyScroll, expander } = props; + const { columns, fixed, tableClassName, getRowKey, handleBodyScroll, expander } = props; const { saveRef } = table; let { useFixedHeader } = table.props; const bodyStyle = { ...table.props.bodyStyle }; @@ -46,6 +46,7 @@ export default function BodyTable(props, { table }) { fixed={fixed} columns={columns} expander={expander} + getRowKey={getRowKey} /> ); diff --git a/src/ExpandableRow.js b/src/ExpandableRow.js index e2eaaa53e..95180e8f3 100644 --- a/src/ExpandableRow.js +++ b/src/ExpandableRow.js @@ -12,24 +12,24 @@ class ExpandableRow extends React.Component { return !this.expandIconAsCell && !expandRowByClick && columnIndex === this.expandIconColumnIndex; } - handleExpandChange = (record, index, event) => { - const { onExpandedChange, expanded } = this.props; + handleExpandChange = (record, event) => { + const { onExpandedChange, expanded, rowKey } = this.props; if (this.expandable) { - onExpandedChange(!expanded, record, event, index); + onExpandedChange(!expanded, record, event, rowKey); } } handleDestroy() { - const { onExpandedChange, index, record } = this.props; + const { onExpandedChange, rowKey, record } = this.props; if (this.expandable) { - onExpandedChange(false, record, null, index); + onExpandedChange(false, record, null, rowKey); } } handleRowClick = (record, index, event) => { const { expandRowByClick, onRowClick } = this.props; if (expandRowByClick) { - this.handleExpandChange(record, index, event); + this.handleExpandChange(record, event); } onRowClick(record, index, event); } diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index 32de32e5e..edccb8e8d 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -72,51 +72,32 @@ class ExpandableTable extends React.Component { } } - handleExpandChange = (expanded, record, event, index) => { - const { expandRowByClick, getRowKey, onExpand } = this.props; - + handleExpandChange = (expanded, record, event, rowKey) => { if (event) { event.preventDefault(); event.stopPropagation(); } - const info = this.findExpandedRow(record); - const expandedRows = this.getExpandedRows().concat(); + const { onExpandedRowsChange, onExpand } = this.props; + const { expandedRowKeys } = this.store.getState(); - if (typeof info !== 'undefined' && !expanded) { - // row was unmounted - const rowKey = this.props.getRowKey(record, index); - let expandedRowIndex = expandedRows.indexOf(rowKey); + if (expanded) { + // row was expaned + expandedRowKeys.push(rowKey); + } else { + // row was collapse + let expandedRowIndex = expandedRowKeys.indexOf(rowKey); if (expandedRowIndex !== -1) { - expandedRows.splice(expandedRowIndex, 1); + expandedRowKeys.splice(expandedRowIndex, 1); } - this.updateExpandedRows(expandedRows); - } else if (!info && expanded) { - // row was collapse - expandedRows.push(getRowKey(record, index)); - this.updateExpandedRows(expandedRows); } - onExpand(expanded, record); - } - updateExpandedRows(expandedRowKeys) { if (!this.props.expandedRowKeys) { this.store.setState({ expandedRowKeys }); } - this.props.onExpandedRowsChange(expandedRowKeys); - } - - findExpandedRow(record, index) { - const rows = this.getExpandedRows().filter(i => i === this.props.getRowKey(record, index)); - return rows[0]; - } - getExpandedRows() { - return this.store.getState().expandedRowKeys; - } - - isRowExpanded(record, index) { - return typeof this.findExpandedRow(record, index) !== 'undefined'; + onExpandedRowsChange(expandedRowKeys); + onExpand(expanded, record); } renderExpandIndentCell = (rows, fixed) => { diff --git a/src/Table.js b/src/Table.js index 57bdbb7af..18225a55c 100644 --- a/src/Table.js +++ b/src/Table.js @@ -82,7 +82,6 @@ export default class Table extends React.Component { props: this.props, columnManager: this.columnManager, saveRef: this.saveRef, - getRowKey: this.getRowKey, }, }; } @@ -342,6 +341,7 @@ export default class Table extends React.Component { columns={columns} fixed={fixed} tableClassName={tableClassName} + getRowKey={this.getRowKey} handleBodyScroll={this.handleBodyScroll} expander={this.expander} /> diff --git a/tests/Table.expandRow.spec.js b/tests/Table.expandRow.spec.js index b85c60627..d5ff0bd5b 100644 --- a/tests/Table.expandRow.spec.js +++ b/tests/Table.expandRow.spec.js @@ -146,7 +146,7 @@ describe('Table.expand', () => { expect(onExpandedRowsChange).toBeCalledWith([1]); }); - it('expand row by click', () => { + fit('expand row by click', () => { const wrapper = mount(createTable({ expandedRowRender })); wrapper.find('ExpandIcon').first().simulate('click'); expect(mountToJson(wrapper)).toMatchSnapshot(); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index 5937625fd..004ea75fc 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -5021,7 +5021,11 @@ exports[`Table.expand expand row by click 1`] = ` ] } defaultExpandAllRows={false} - defaultExpandedRowKeys={Array []} + defaultExpandedRowKeys={ + Array [ + 0, + ] + } emptyText={[Function]} expandIconAsCell={false} expandIconColumnIndex={0} @@ -5151,7 +5155,9 @@ exports[`Table.expand expand row by click 1`] = ` }, ], "defaultExpandAllRows": false, - "defaultExpandedRowKeys": Array [], + "defaultExpandedRowKeys": Array [ + 0, + ], "emptyText": [Function], "expandIconAsCell": false, "expandIconColumnIndex": 0, @@ -5281,7 +5287,9 @@ exports[`Table.expand expand row by click 1`] = ` }, ], "defaultExpandAllRows": false, - "defaultExpandedRowKeys": Array [], + "defaultExpandedRowKeys": Array [ + 0, + ], "emptyText": [Function], "expandIconAsCell": false, "expandIconColumnIndex": 0, @@ -5316,6 +5324,7 @@ exports[`Table.expand expand row by click 1`] = ` } } fixed={undefined} + getRowKey={[Function]} handleBodyScroll={[Function]} key="body" tableClassName="" @@ -5417,7 +5426,9 @@ exports[`Table.expand expand row by click 1`] = ` }, ], "defaultExpandAllRows": false, - "defaultExpandedRowKeys": Array [], + "defaultExpandedRowKeys": Array [ + 0, + ], "emptyText": [Function], "expandIconAsCell": false, "expandIconColumnIndex": 0, @@ -5452,6 +5463,7 @@ exports[`Table.expand expand row by click 1`] = ` } } fixed={undefined} + getRowKey={[Function]} hasBody={true} hasHead={true} tableClassName="" @@ -5547,7 +5559,9 @@ exports[`Table.expand expand row by click 1`] = ` }, ], "defaultExpandAllRows": false, - "defaultExpandedRowKeys": Array [], + "defaultExpandedRowKeys": Array [ + 0, + ], "emptyText": [Function], "expandIconAsCell": false, "expandIconColumnIndex": 0, @@ -5582,6 +5596,7 @@ exports[`Table.expand expand row by click 1`] = ` } } fixed={undefined} + getRowKey={[Function]} hasBody={true} hasHead={true} store={ @@ -5727,7 +5742,9 @@ exports[`Table.expand expand row by click 1`] = ` }, ], "defaultExpandAllRows": false, - "defaultExpandedRowKeys": Array [], + "defaultExpandedRowKeys": Array [ + 0, + ], "emptyText": [Function], "expandIconAsCell": false, "expandIconColumnIndex": 0, @@ -5973,7 +5990,11 @@ exports[`Table.expand expand row by click 1`] = ` ] } defaultExpandAllRows={false} - defaultExpandedRowKeys={Array []} + defaultExpandedRowKeys={ + Array [ + 0, + ] + } emptyText={[Function]} expandIconAsCell={false} expandIconColumnIndex={0} @@ -6094,7 +6115,11 @@ exports[`Table.expand expand row by click 1`] = ` ] } defaultExpandAllRows={false} - defaultExpandedRowKeys={Array []} + defaultExpandedRowKeys={ + Array [ + 0, + ] + } emptyText={[Function]} expandIconAsCell={false} expandIconColumnIndex={0} @@ -6571,7 +6596,11 @@ exports[`Table.expand expand row by click 1`] = ` ] } defaultExpandAllRows={false} - defaultExpandedRowKeys={Array []} + defaultExpandedRowKeys={ + Array [ + 0, + ] + } emptyText={[Function]} expandIconAsCell={false} expandIconColumnIndex={0} @@ -6692,7 +6721,11 @@ exports[`Table.expand expand row by click 1`] = ` ] } defaultExpandAllRows={false} - defaultExpandedRowKeys={Array []} + defaultExpandedRowKeys={ + Array [ + 0, + ] + } emptyText={[Function]} expandIconAsCell={false} expandIconColumnIndex={0} From 3c1341f8b5dcd249078e5755599747733fc82a81 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Fri, 20 Oct 2017 16:44:04 +0800 Subject: [PATCH 18/26] Remove unsed method --- src/Table.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Table.js b/src/Table.js index 18225a55c..5592d7041 100644 --- a/src/Table.js +++ b/src/Table.js @@ -139,10 +139,6 @@ export default class Table extends React.Component { return key === undefined ? index : key; } - getRows = (columns, fixed) => { - return this.getRowsByData(this.props.data, true, 0, columns, fixed); - } - setScrollPosition(position) { this.scrollPosition = position; if (this.tableNode) { From 02a586da2e666af4e5e88a9ea1227587a116e766 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Fri, 20 Oct 2017 17:38:45 +0800 Subject: [PATCH 19/26] Remove ExpandedRowHeigh --- src/BaseTable.js | 46 +++++++++++++-------------------- src/ExpandableTable.js | 24 +++++------------ src/ExpandedRowHeigh.js | 57 ----------------------------------------- src/TableRow.js | 49 ++++++++++++++++++++++++++++++++--- 4 files changed, 70 insertions(+), 106 deletions(-) delete mode 100644 src/ExpandedRowHeigh.js diff --git a/src/BaseTable.js b/src/BaseTable.js index 101779d6a..eae7bb4d4 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -5,7 +5,6 @@ import ColGroup from './ColGroup'; import TableHeader from './TableHeader'; import TableRow from './TableRow'; import ExpandableRow from './ExpandableRow'; -import ExpandedRowHeigh from './ExpandedRowHeigh'; class BaseTable extends React.Component { static propTypes = { @@ -86,35 +85,26 @@ class BaseTable extends React.Component { onExpandedChange={expander.handleExpandChange} > {( expandableRow ) => ( - - {({ height }) => ( - - )} - + prefixCls={rowPrefixCls} + childrenColumnName={childrenColumnName} + columns={leafColumns} + onRowDoubleClick={onRowDoubleClick} + onRowContextMenu={onRowContextMenu} + onRowMouseEnter={onRowMouseEnter} + onRowMouseLeave={onRowMouseLeave} + {...onHoverProps} + hoverKey={key} + rowKey={key} + ancestorKeys={ancestorKeys} + ref={rowRef(record, i, indent)} + {...expandableRow} + /> )} ); diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index edccb8e8d..b2e6de2c4 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -2,7 +2,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'mini-store'; import TableRow from './TableRow'; -import ExpandedRowHeigh from './ExpandedRowHeigh'; class ExpandableTable extends React.Component { static propTypes = { @@ -143,24 +142,15 @@ class ExpandableTable extends React.Component { const rowKey = `${ancestorKeys[0]}-extra-row`; return ( - - {({ height, saveRowRef }) => ( - - )} - + ancestorKeys={ancestorKeys} + prefixCls={`${prefixCls}-expanded-row`} + indent={1} + /> ); } diff --git a/src/ExpandedRowHeigh.js b/src/ExpandedRowHeigh.js deleted file mode 100644 index 2255d598f..000000000 --- a/src/ExpandedRowHeigh.js +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; -import { connect } from 'mini-store'; - -class ExpandedRowHeigh extends React.Component { - componentDidUpdate() { - if (!this.props.fixed && this.rowRef && !this.set) { - this.setHeight(); - } - } - - setHeight() { - const { store, rowKey } = this.props; - const { expandedRowsHeight } = store.getState(); - const height = this.rowRef.getBoundingClientRect().height; - expandedRowsHeight[rowKey] = height; - store.setState({ expandedRowsHeight }); - this.set = true; - } - - saveRowRef = (node) => { - this.rowRef = node; - } - - render() { - const { children, height } = this.props; - return children({ - height, - saveRowRef: this.saveRowRef, - }); - } -} - -function getRowHeight(state, props) { - const { expandedRowsHeight, fixedColumnsBodyRowsHeight } = state; - const { fixed, index, rowKey } = props; - - if (!fixed) { - return null; - } - - - if (expandedRowsHeight[rowKey]) { - return expandedRowsHeight[rowKey]; - } - - if (fixedColumnsBodyRowsHeight[index]) { - return fixedColumnsBodyRowsHeight[index]; - } - - return null; -} - -export default connect((state, props) => { - return { - height: getRowHeight(state, props), - }; -})(ExpandedRowHeigh) diff --git a/src/TableRow.js b/src/TableRow.js index 43c7fb7dc..70cadc5dc 100644 --- a/src/TableRow.js +++ b/src/TableRow.js @@ -52,6 +52,23 @@ class TableRow extends React.Component { } } + setHeight() { + const { store, rowKey } = this.props; + const { expandedRowsHeight } = store.getState(); + const height = this.rowRef.getBoundingClientRect().height; + expandedRowsHeight[rowKey] = height; + store.setState({ expandedRowsHeight }); + } + + saveRowRef = (node) => { + this.rowRef = node; + if (node) { + if (!this.props.fixed) { + this.setHeight(); + } + } + } + onRowClick = (event) => { const { record, index, onRowClick } = this.props; onRowClick(record, index, event); @@ -94,7 +111,6 @@ class TableRow extends React.Component { visible, height, hovered, - saveRowRef, hasExpandIcon, addExpandIconCell, renderExpandIcon, @@ -137,7 +153,7 @@ class TableRow extends React.Component { return ( { +function getRowHeight(state, props) { + const { expandedRowsHeight, fixedColumnsBodyRowsHeight } = state; + const { fixed, index, rowKey } = props; + + if (!fixed) { + return null; + } + + + if (expandedRowsHeight[rowKey]) { + return expandedRowsHeight[rowKey]; + } + + if (fixedColumnsBodyRowsHeight[index]) { + return fixedColumnsBodyRowsHeight[index]; + } + + return null; +} + +export default connect((state, props) => { + const { currentHoverKey, expandedRowKeys } = state; + const { rowKey, ancestorKeys } = props; + const visible = ancestorKeys.length === 0 || ancestorKeys.every(k => ~expandedRowKeys.indexOf(k)); + return ({ + visible, hovered: currentHoverKey === rowKey, - visible: ancestorKeys.length === 0 || ancestorKeys.every(k => ~expandedRowKeys.indexOf(k)), + height: getRowHeight(state, props), }) })(TableRow); From eec8c9f832d3612041d0c5ed5a230903fb9ab25d Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Fri, 20 Oct 2017 18:14:21 +0800 Subject: [PATCH 20/26] Don't need hoverKey --- src/BaseTable.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/BaseTable.js b/src/BaseTable.js index eae7bb4d4..ed270cef9 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -99,7 +99,6 @@ class BaseTable extends React.Component { onRowMouseEnter={onRowMouseEnter} onRowMouseLeave={onRowMouseLeave} {...onHoverProps} - hoverKey={key} rowKey={key} ancestorKeys={ancestorKeys} ref={rowRef(record, i, indent)} From d6fa0c6c991a369e183921a4fd0ad2e886526d51 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Sun, 22 Oct 2017 02:01:30 +0800 Subject: [PATCH 21/26] Lint fix --- examples/dropdown.js | 8 +- examples/expandedRowRender.js | 18 +- examples/key.js | 9 +- src/BaseTable.js | 21 +- src/BodyTable.js | 7 +- src/ExpandableRow.js | 34 +- src/ExpandableTable.js | 14 +- src/HeadTable.js | 6 +- src/Table.js | 8 +- src/TableHeader.js | 1 + src/TableHeaderRow.js | 4 +- src/TableRow.js | 55 +- tests/Table.spec.js | 12 +- .../Table.expandRow.spec.js.snap | 982 ++++++++---------- tests/setup.js | 2 +- 15 files changed, 576 insertions(+), 605 deletions(-) diff --git a/examples/dropdown.js b/examples/dropdown.js index d09264a22..38c2f5e2c 100644 --- a/examples/dropdown.js +++ b/examples/dropdown.js @@ -18,13 +18,13 @@ for (let i = 0; i < 10; i++) { }); } -class Test extends React.Component { - filters = [] - +class Demo extends React.Component { state = { visible: false, } + filters = [] + handleVisibleChange = (visible) => { this.setState({ visible }); } @@ -105,7 +105,7 @@ class Test extends React.Component { ReactDOM.render(

use dropdown

- +
, document.getElementById('__react-content') ); diff --git a/examples/expandedRowRender.js b/examples/expandedRowRender.js index 043a2fdd4..6e04bcc12 100644 --- a/examples/expandedRowRender.js +++ b/examples/expandedRowRender.js @@ -10,14 +10,7 @@ const tableData = [ { key: 2, a: '1333', c: 'eee', d: 2 }, ]; -class App extends React.Component { - columns = [ - { title: 'title 1', dataIndex: 'a', key: 'a', width: 100 }, - { title: 'title 2', dataIndex: 'b', key: 'b', width: 100 }, - { title: 'title 3', dataIndex: 'c', key: 'c', width: 200 }, - { title: 'Operation', dataIndex: '', key: 'x', render: this.renderAction }, - ] - +class Demo extends React.Component { state = { data: tableData, expandedRowKeys: [], @@ -47,6 +40,13 @@ class App extends React.Component { }); } + columns = [ + { title: 'title 1', dataIndex: 'a', key: 'a', width: 100 }, + { title: 'title 2', dataIndex: 'b', key: 'b', width: 100 }, + { title: 'title 3', dataIndex: 'c', key: 'c', width: 200 }, + { title: 'Operation', dataIndex: '', key: 'x', render: this.renderAction }, + ] + toggleButton() { if (this.state.expandedRowKeys.length) { const closeAll = () => this.setState({ expandedRowKeys: [] }); @@ -108,7 +108,7 @@ class App extends React.Component { ReactDOM.render(

expandedRowRender

- +
, document.getElementById('__react-content') ); diff --git a/examples/key.js b/examples/key.js index 4f36cef5b..d468ba201 100644 --- a/examples/key.js +++ b/examples/key.js @@ -1,6 +1,7 @@ /* eslint-disable no-console,func-names,react/no-multi-comp */ import React from 'react'; import ReactDOM from 'react-dom'; +import PropTypes from 'prop-types'; import Table from 'rc-table'; import 'rc-table/assets/index.less'; @@ -11,7 +12,11 @@ const CheckBox = ({ id }) => ( ); -class MyTable extends React.Component { +class Demo extends React.Component { + static propTypes = { + data: PropTypes.array.isRequired, + } + constructor(props) { super(props); @@ -59,7 +64,7 @@ const data = [{ a: '123' }, { a: 'cdd', b: 'edd' }, { a: '1333', c: 'eee', d: 2 ReactDOM.render(

specify key

- +
, document.getElementById('__react-content') ); diff --git a/src/BaseTable.js b/src/BaseTable.js index ed270cef9..91d3cc867 100644 --- a/src/BaseTable.js +++ b/src/BaseTable.js @@ -8,11 +8,17 @@ import ExpandableRow from './ExpandableRow'; class BaseTable extends React.Component { static propTypes = { - fixed: PropTypes.string, + fixed: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.bool, + ]), columns: PropTypes.array.isRequired, tableClassName: PropTypes.string.isRequired, hasHead: PropTypes.bool.isRequired, hasBody: PropTypes.bool.isRequired, + store: PropTypes.object.isRequired, + expander: PropTypes.object.isRequired, + getRowKey: PropTypes.func, } static contextTypes = { @@ -27,13 +33,9 @@ class BaseTable extends React.Component { renderRows = (renderData, indent, ancestorKeys = []) => { const { table } = this.context; - const { - columnManager, - onExpanded, - } = table; + const { columnManager } = table; const { prefixCls, - data, childrenColumnName, rowClassName, rowRef, @@ -43,14 +45,13 @@ class BaseTable extends React.Component { onRowMouseEnter, onRowMouseLeave, } = table.props; - const { getRowKey, columns, fixed, expander } = this.props; + const { getRowKey, fixed, expander } = this.props; - let rows = []; + const rows = []; for (let i = 0; i < renderData.length; i++) { const record = renderData[i]; const key = getRowKey(record, i); - const childrenData = record[childrenColumnName]; const className = typeof rowClassName === 'string' ? rowClassName : rowClassName(record, i, indent); @@ -84,7 +85,7 @@ class BaseTable extends React.Component { needIndentSpaced={expander.needIndentSpaced} onExpandedChange={expander.handleExpandChange} > - {( expandableRow ) => ( + {(expandableRow) => ( // eslint-disable-line { const { expandRowByClick } = this.props; - return !this.expandIconAsCell && !expandRowByClick && columnIndex === this.expandIconColumnIndex; + return !this.expandIconAsCell && + !expandRowByClick && + columnIndex === this.expandIconColumnIndex; } handleExpandChange = (record, event) => { @@ -35,7 +62,7 @@ class ExpandableRow extends React.Component { } renderExpandIcon = () => { - const { prefixCls, expanded, record, needIndentSpaced, onExpandedChange } = this.props; + const { prefixCls, expanded, record, needIndentSpaced } = this.props; return ( ({ expanded: !!~expandedRowKeys.indexOf(rowKey), }))(ExpandableRow); - diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index b2e6de2c4..fd42721a7 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -11,10 +11,16 @@ class ExpandableTable extends React.Component { defaultExpandAllRows: PropTypes.bool, defaultExpandedRowKeys: PropTypes.array, expandIconColumnIndex: PropTypes.number, + expandedRowRender: PropTypes.func, childrenColumnName: PropTypes.string, indentSize: PropTypes.number, onExpand: PropTypes.func, onExpandedRowsChange: PropTypes.func, + columnManager: PropTypes.object.isRequired, + store: PropTypes.object.isRequired, + prefixCls: PropTypes.string.isRequired, + data: PropTypes.array, + children: PropTypes.func.isRequired, } static defaultProps = { @@ -85,7 +91,7 @@ class ExpandableTable extends React.Component { expandedRowKeys.push(rowKey); } else { // row was collapse - let expandedRowIndex = expandedRowKeys.indexOf(rowKey); + const expandedRowIndex = expandedRowKeys.indexOf(rowKey); if (expandedRowIndex !== -1) { expandedRowKeys.splice(expandedRowIndex, 1); } @@ -101,7 +107,7 @@ class ExpandableTable extends React.Component { renderExpandIndentCell = (rows, fixed) => { const { prefixCls, expandIconAsCell } = this.props; - if (!expandIconAsCell || fixed == 'right') { + if (!expandIconAsCell || fixed === 'right') { return; } @@ -155,7 +161,7 @@ class ExpandableTable extends React.Component { } renderRows = (renderRows, record, index, indent, fixed, parentKey, ancestorKeys) => { - const { expandedRowClassName, columns, expandedRowRender, childrenColumnName } = this.props; + const { expandedRowClassName, expandedRowRender, childrenColumnName } = this.props; const childrenData = record[childrenColumnName]; const expandedRowContent = expandedRowRender && expandedRowRender(record, index, indent); const nextAncestorKeys = [...ancestorKeys, parentKey]; @@ -167,7 +173,7 @@ class ExpandableTable extends React.Component { expandedRowClassName(record, index, indent), nextAncestorKeys, fixed, - ) + ), ]; } diff --git a/src/HeadTable.js b/src/HeadTable.js index 522dfe1bc..6e088ee8a 100644 --- a/src/HeadTable.js +++ b/src/HeadTable.js @@ -45,10 +45,14 @@ export default function HeadTable(props, { table }) { } HeadTable.propTypes = { - fixed: PropTypes.string, + fixed: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.bool, + ]), columns: PropTypes.array.isRequired, tableClassName: PropTypes.string.isRequired, handleBodyScrollLeft: PropTypes.func.isRequired, + expander: PropTypes.object.isRequired, }; HeadTable.contextTypes = { diff --git a/src/Table.js b/src/Table.js index 5592d7041..36f5700a6 100644 --- a/src/Table.js +++ b/src/Table.js @@ -278,7 +278,7 @@ export default class Table extends React.Component { const table = [ this.renderTable({ - columns: this.columnManager.groupedColumns() + columns: this.columnManager.groupedColumns(), }), this.renderEmptyText(), this.renderFooter(), @@ -286,7 +286,7 @@ export default class Table extends React.Component { return scrollable ? (
{table}
- ): table; + ) : table; } renderLeftFixedTable() { @@ -296,7 +296,7 @@ export default class Table extends React.Component {
{this.renderTable({ columns: this.columnManager.leftColumns(), - fixed: 'left', + fixed: 'left', })}
); @@ -309,7 +309,7 @@ export default class Table extends React.Component {
{this.renderTable({ columns: this.columnManager.rightColumns(), - fixed: 'right', + fixed: 'right', })}
); diff --git a/src/TableHeader.js b/src/TableHeader.js index 3d555b1f3..51f124fcf 100644 --- a/src/TableHeader.js +++ b/src/TableHeader.js @@ -65,6 +65,7 @@ export default function TableHeader(props, { table }) { TableHeader.propTypes = { fixed: PropTypes.string, columns: PropTypes.array.isRequired, + expander: PropTypes.object.isRequired, }; TableHeader.contextTypes = { diff --git a/src/TableHeaderRow.js b/src/TableHeaderRow.js index 42a8b129c..6b2301684 100644 --- a/src/TableHeaderRow.js +++ b/src/TableHeaderRow.js @@ -13,7 +13,7 @@ function TableHeaderRow({ row, height }) { function getRowHeight(state, props) { const { fixedColumnsHeadRowsHeight } = state; - const { fixed, columns, rows } = props; + const { columns, rows } = props; const headerHeight = fixedColumnsHeadRowsHeight[0]; if (headerHeight && columns) { @@ -28,5 +28,5 @@ function getRowHeight(state, props) { export default connect((state, props) => { return { height: getRowHeight(state, props), - } + }; })(TableHeaderRow); diff --git a/src/TableRow.js b/src/TableRow.js index 70cadc5dc..d26d0ac7a 100644 --- a/src/TableRow.js +++ b/src/TableRow.js @@ -19,11 +19,23 @@ class TableRow extends React.Component { PropTypes.number, ]), index: PropTypes.number, - rowKey: PropTypes.any, + rowKey: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]).isRequired, className: PropTypes.string, indent: PropTypes.number, indentSize: PropTypes.number, - expandedRow: PropTypes.bool, + hasExpandIcon: PropTypes.func.isRequired, + hovered: PropTypes.bool.isRequired, + visible: PropTypes.bool.isRequired, + store: PropTypes.object.isRequired, + fixed: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.bool, + ]), + renderExpandIcon: PropTypes.func, + renderExpandIconCell: PropTypes.func, } static defaultProps = { @@ -52,23 +64,6 @@ class TableRow extends React.Component { } } - setHeight() { - const { store, rowKey } = this.props; - const { expandedRowsHeight } = store.getState(); - const height = this.rowRef.getBoundingClientRect().height; - expandedRowsHeight[rowKey] = height; - store.setState({ expandedRowsHeight }); - } - - saveRowRef = (node) => { - this.rowRef = node; - if (node) { - if (!this.props.fixed) { - this.setHeight(); - } - } - } - onRowClick = (event) => { const { record, index, onRowClick } = this.props; onRowClick(record, index, event); @@ -96,6 +91,23 @@ class TableRow extends React.Component { onRowMouseLeave(record, index, event); } + setHeight() { + const { store, rowKey } = this.props; + const { expandedRowsHeight } = store.getState(); + const height = this.rowRef.getBoundingClientRect().height; + expandedRowsHeight[rowKey] = height; + store.setState({ expandedRowsHeight }); + } + + saveRowRef = (node) => { + this.rowRef = node; + if (node) { + if (!this.props.fixed) { + this.setHeight(); + } + } + } + render() { if (!this.shouldRender) { return null; @@ -112,9 +124,8 @@ class TableRow extends React.Component { height, hovered, hasExpandIcon, - addExpandIconCell, renderExpandIcon, - renderExpandIconCell + renderExpandIconCell, } = this.props; let { className } = this.props; @@ -197,5 +208,5 @@ export default connect((state, props) => { visible, hovered: currentHoverKey === rowKey, height: getRowHeight(state, props), - }) + }); })(TableRow); diff --git a/tests/Table.spec.js b/tests/Table.spec.js index 491aca955..2da619e96 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -77,20 +77,20 @@ describe('Table', () => { describe('rowKey', () => { it('uses record.key', () => { const wrapper = mount(createTable()); - expect(wrapper.find('TableRow').at(0).prop('hoverKey')).toBe('key0'); - expect(wrapper.find('TableRow').at(1).prop('hoverKey')).toBe('key1'); + expect(wrapper.find('TableRow').at(0).prop('rowKey')).toBe('key0'); + expect(wrapper.find('TableRow').at(1).prop('rowKey')).toBe('key1'); }); it('sets by rowKey', () => { const wrapper = mount(createTable({ rowKey: 'name' })); - expect(wrapper.find('TableRow').at(0).prop('hoverKey')).toBe('Lucy'); - expect(wrapper.find('TableRow').at(1).prop('hoverKey')).toBe('Jack'); + expect(wrapper.find('TableRow').at(0).prop('rowKey')).toBe('Lucy'); + expect(wrapper.find('TableRow').at(1).prop('rowKey')).toBe('Jack'); }); it('sets by rowKey function', () => { const wrapper = mount(createTable({ rowKey: (record) => `${record.key}1` })); - expect(wrapper.find('TableRow').at(0).prop('hoverKey')).toBe('key01'); - expect(wrapper.find('TableRow').at(1).prop('hoverKey')).toBe('key11'); + expect(wrapper.find('TableRow').at(0).prop('rowKey')).toBe('key01'); + expect(wrapper.find('TableRow').at(1).prop('rowKey')).toBe('key11'); }); }); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index 004ea75fc..87eaf940b 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -6163,15 +6163,89 @@ exports[`Table.expand expand row by click 1`] = ` style={Object {}} useFixedHeader={false} > - - - + - } - expandIconColumnIndex={0} - expandRowByClick={false} - fixed={undefined} - hasExpandIcon={[Function]} - height={null} - hoverKey={0} - hovered={false} indent={0} indentSize={15} index={0} - onHover={[Function]} - onRowClick={[Function]} - onRowContextMenu={[Function]} - onRowDoubleClick={[Function]} - onRowMouseEnter={[Function]} - onRowMouseLeave={[Function]} + key="name" prefixCls="rc-table-row" record={ Object { @@ -6265,115 +6305,24 @@ exports[`Table.expand expand row by click 1`] = ` "name": "Lucy", } } - renderExpandIcon={[Function]} - renderExpandIconCell={[Function]} - rowKey={0} - store={ - Object { - "getState": [Function], - "setState": [Function], - "subscribe": [Function], - } - } - visible={true} > - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - - - - - - Lucy - - - + - - 27 - - - - - - - + /> +
+ Lucy + + + + + 27 + + + +
+ - - - + - - - - -

- extra data -

- -
- -
-
-
-
+

+ extra data +

+ + + + + - - - + - } - expandIconColumnIndex={0} - expandRowByClick={false} - fixed={undefined} - hasExpandIcon={[Function]} - height={null} - hoverKey={1} - hovered={false} indent={0} indentSize={15} index={1} - onHover={[Function]} - onRowClick={[Function]} - onRowContextMenu={[Function]} - onRowDoubleClick={[Function]} - onRowMouseEnter={[Function]} - onRowMouseLeave={[Function]} + key="name" prefixCls="rc-table-row" record={ Object { @@ -6871,59 +6867,24 @@ exports[`Table.expand expand row by click 1`] = ` "name": "Jack", } } - renderExpandIcon={[Function]} - renderExpandIconCell={[Function]} - rowKey={1} - store={ - Object { - "getState": [Function], - "setState": [Function], - "subscribe": [Function], - } - } - visible={true} > - - - } - indent={0} - indentSize={15} - index={1} - key="name" + /> + - - - - - - Jack - - - - - 28 - - - - - - - + /> + + Jack + + + + + 28 + + + + + - - - - - - - + visible={false} + /> + diff --git a/tests/setup.js b/tests/setup.js index 3df8ba4d3..684b8a6fb 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -1,4 +1,4 @@ -global.requestAnimationFrame = global.requestAnimationFrame || function (cb) { // eslint-disable-line +global.requestAnimationFrame = global.requestAnimationFrame || function requestAnimationFrame(cb) { return setTimeout(cb, 0); }; From 28d72ad97825e93fbbc690fc9a7471130a6ec306 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Sun, 22 Oct 2017 02:19:41 +0800 Subject: [PATCH 22/26] Update snapshot --- package.json | 6 +- tests/Table.expandRow.spec.js | 23 +- tests/Table.fixedColumns.spec.js | 3 +- tests/Table.spec.js | 37 +- .../Table.expandRow.spec.js.snap | 2294 +---------------- 5 files changed, 121 insertions(+), 2242 deletions(-) diff --git a/package.json b/package.json index 71857513d..e8db683e5 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,10 @@ ], "transform": { "\\.jsx?$": "./node_modules/rc-tools/scripts/jestPreprocessor.js" - } + }, + "snapshotSerializers": [ + "enzyme-to-json/serializer" + ] }, "dependencies": { "babel-runtime": "6.x", @@ -86,7 +89,6 @@ "rc-menu": "^5.0.11", "rc-tools": "7.x", "react": "^16.0.0", - "react-addons-test-utils": "^15.3.1", "react-dom": "^16.0.0", "react-test-renderer": "^16.0.0" }, diff --git a/tests/Table.expandRow.spec.js b/tests/Table.expandRow.spec.js index d5ff0bd5b..93e2d52fb 100644 --- a/tests/Table.expandRow.spec.js +++ b/tests/Table.expandRow.spec.js @@ -1,7 +1,6 @@ /* eslint-disable no-undef */ import React from 'react'; import { render, mount } from 'enzyme'; -import { renderToJson, mountToJson } from 'enzyme-to-json'; import Table from '../src'; describe('Table.expand', () => { @@ -24,7 +23,7 @@ describe('Table.expand', () => { it('renders expand row correctly', () => { const wrapper = render(createTable({ expandedRowRender })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders tree row correctly', () => { @@ -35,7 +34,7 @@ describe('Table.expand', () => { { key: 1, name: 'Jack', age: 28 }, ]; const wrapper = render(createTable({ data: localData })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders expand icon as cell', () => { @@ -43,7 +42,7 @@ describe('Table.expand', () => { expandedRowRender, expandIconAsCell: true, })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders expand icon to the specify column', () => { @@ -51,7 +50,7 @@ describe('Table.expand', () => { expandedRowRender, expandIconColumnIndex: 1, })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders nested data correctly', () => { @@ -71,7 +70,7 @@ describe('Table.expand', () => { }, ]; const wrapper = render(createTable({ data: localData })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('expand all rows by default', () => { @@ -79,7 +78,7 @@ describe('Table.expand', () => { expandedRowRender, defaultExpandAllRows: true, })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('expand rows by defaultExpandedRowKeys', () => { @@ -87,7 +86,7 @@ describe('Table.expand', () => { expandedRowRender, defaultExpandedRowKeys: [1], })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('controlled by expandedRowKeys', () => { @@ -95,9 +94,9 @@ describe('Table.expand', () => { expandedRowRender, expandedRowKeys: [0], })); - expect(mountToJson(wrapper)).toMatchSnapshot(); + expect(wrapper.render()).toMatchSnapshot(); wrapper.setProps({ expandedRowKeys: [1] }); - expect(mountToJson(wrapper)).toMatchSnapshot(); + expect(wrapper.render()).toMatchSnapshot(); }); it('renders expend row class correctly', () => { @@ -107,7 +106,7 @@ describe('Table.expand', () => { expandedRowKeys: [0], expandedRowClassName, })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); expect(expandedRowClassName).toBeCalledWith(data[0], 0, 0); }); @@ -149,6 +148,6 @@ describe('Table.expand', () => { fit('expand row by click', () => { const wrapper = mount(createTable({ expandedRowRender })); wrapper.find('ExpandIcon').first().simulate('click'); - expect(mountToJson(wrapper)).toMatchSnapshot(); + expect(wrapper.render()).toMatchSnapshot(); }); }); diff --git a/tests/Table.fixedColumns.spec.js b/tests/Table.fixedColumns.spec.js index 22d851507..f3c8deb64 100644 --- a/tests/Table.fixedColumns.spec.js +++ b/tests/Table.fixedColumns.spec.js @@ -1,7 +1,6 @@ /* eslint-disable no-undef */ import React from 'react'; import { render, mount } from 'enzyme'; -import { renderToJson } from 'enzyme-to-json'; import Table from '../src'; describe('Table.fixedColumns', () => { @@ -47,7 +46,7 @@ describe('Table.fixedColumns', () => { scroll={{ x: 1200 }} /> ); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('toggles hover class when user hovering', () => { diff --git a/tests/Table.spec.js b/tests/Table.spec.js index 2da619e96..22aab3717 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -1,7 +1,6 @@ /* eslint-disable no-undef, no-console */ import React from 'react'; import { render, mount } from 'enzyme'; -import { renderToJson } from 'enzyme-to-json'; import Table from '../src'; describe('Table', () => { @@ -28,34 +27,34 @@ describe('Table', () => { prefixCls: 'test-prefix', className: 'test-class-name', })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders empty text correctly', () => { const wrapper1 = render(createTable({ data: [], emptyText: 'No data' })); const wrapper2 = render(createTable({ data: [], emptyText: () => 'No data' })); - expect(renderToJson(wrapper1)).toMatchSnapshot(); - expect(renderToJson(wrapper2)).toMatchSnapshot(); + expect(wrapper1).toMatchSnapshot(); + expect(wrapper2).toMatchSnapshot(); }); it('renders without header', () => { const wrapper = render(createTable({ showHeader: false })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders fixed header correctly', () => { const wrapper = render(createTable({ useFixedHeader: true })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders title correctly', () => { const wrapper = render(createTable({ title: () =>

title

})); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders footer correctly', () => { const wrapper = render(createTable({ footer: () =>

footer

})); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders table body to the wrapper', () => { @@ -65,7 +64,7 @@ describe('Table', () => { ); const wrapper = render(createTable({ getBodyWrapper })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); xit('sets row refs', () => { @@ -97,17 +96,17 @@ describe('Table', () => { describe('scroll', () => { it('renders scroll.x is true', () => { const wrapper = render(createTable({ scroll: { x: true } })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders scroll.x is a number', () => { const wrapper = render(createTable({ scroll: { x: 200 } })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders scroll.y is a number', () => { const wrapper = render(createTable({ scroll: { y: 200 } })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('fire scroll event', () => { @@ -227,7 +226,7 @@ describe('Table', () => { }, ]; const wrapper = render(createTable({ columns })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders custom cell correctly', () => { @@ -240,7 +239,7 @@ describe('Table', () => { }, ]; const wrapper = render(createTable({ columns })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('fires cell click event', () => { @@ -286,7 +285,7 @@ describe('Table', () => { { key: 'key1', name: { first: 'Terry', last: 'Garner' } }, ]; const wrapper = render(createTable({ columns, data: localData })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); }); @@ -339,7 +338,7 @@ describe('Table', () => { { key: 'key1', firstName: 'Terry', lastName: 'Garner' }, ]; const wrapper = render(createTable({ columns, data: localData })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders rowSpan correctly', () => { @@ -372,7 +371,7 @@ describe('Table', () => { { key: 'key1', firstName: 'Terry', lastName: 'Garner' }, ]; const wrapper = render(createTable({ columns, data: localData })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('shows error if no rowKey specify', () => { @@ -432,13 +431,13 @@ describe('Table', () => { const wrapper = render(createTable({ rowClassName: 'test-row-class-name-asStr', })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); it('renders correctly RowClassName as function', () => { const wrapper = render(createTable({ rowClassName: () => 'test-row-class-name-asFn', })); - expect(renderToJson(wrapper)).toMatchSnapshot(); + expect(wrapper).toMatchSnapshot(); }); }); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index 87eaf940b..e1283e60e 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -4795,2220 +4795,100 @@ exports[`Table.expand expand all rows by default 1`] = ` `; exports[`Table.expand expand row by click 1`] = ` - - - - -
+
+ + + -
+
+ + + + + - - -
- - -
+ Name + + Age +
- - - - - - - - - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - - - - - - - - - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 28, - "key": 1, - "name": "Jack", - } - } - > - - - - - - - - - - - - - - -
- Name - - Age -
- - - - - Lucy - - 27 -
-

- extra data -

-
- - - - - Jack - - 28 -
- - -
- -
-
-
- - - + + + Lucy + + + 27 + + + + +

+ extra data +

+ + + + + + + Jack + + + 28 + + + + + + + `; exports[`Table.expand expand rows by defaultExpandedRowKeys 1`] = ` From ff673dbd03316660be8321ebc646c2176706bb37 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Mon, 23 Oct 2017 11:03:15 +0800 Subject: [PATCH 23/26] Upgrade mini-store --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8db683e5..e75884906 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "babel-runtime": "6.x", "component-classes": "^1.2.6", "lodash.get": "^4.4.2", - "mini-store": "^1.0.0", + "mini-store": "^1.0.2", "prop-types": "^15.5.8", "rc-util": "^4.0.4", "shallowequal": "^1.0.2", From 6cd1abd97247d67c5920040a08eb17f7fb7d9d62 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Mon, 23 Oct 2017 11:06:46 +0800 Subject: [PATCH 24/26] Fix example --- examples/fixedColumnsAndHeader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/fixedColumnsAndHeader.js b/examples/fixedColumnsAndHeader.js index 18f9c8a23..e62776a59 100644 --- a/examples/fixedColumnsAndHeader.js +++ b/examples/fixedColumnsAndHeader.js @@ -34,6 +34,6 @@ const data = [ ReactDOM.render(

Fixed columns and header

- +
, document.getElementById('__react-content')); From db580bc90e93e890e27ac351f9eb5cd8ceaebbc4 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Mon, 23 Oct 2017 11:43:52 +0800 Subject: [PATCH 25/26] Add expand row and fixed column test --- tests/Table.expandRow.spec.js | 39 +- .../Table.expandRow.spec.js.snap | 5080 ++--------------- 2 files changed, 442 insertions(+), 4677 deletions(-) diff --git a/tests/Table.expandRow.spec.js b/tests/Table.expandRow.spec.js index 93e2d52fb..dc69f508e 100644 --- a/tests/Table.expandRow.spec.js +++ b/tests/Table.expandRow.spec.js @@ -4,19 +4,22 @@ import { render, mount } from 'enzyme'; import Table from '../src'; describe('Table.expand', () => { - const columns = [ + const expandedRowRender = () =>

extra data

; + + const sampleColumns = [ { title: 'Name', dataIndex: 'name', key: 'name' }, { title: 'Age', dataIndex: 'age', key: 'age' }, ]; - const data = [ + + const sampleData = [ { key: 0, name: 'Lucy', age: 27 }, { key: 1, name: 'Jack', age: 28 }, ]; - const expandedRowRender = () =>

extra data

; + const createTable = (props) => (
); @@ -27,13 +30,27 @@ describe('Table.expand', () => { }); it('renders tree row correctly', () => { - const localData = [ + const data = [ { key: 0, name: 'Lucy', age: 27, children: [ { key: 2, name: 'Jim', age: 1 }, ] }, { key: 1, name: 'Jack', age: 28 }, ]; - const wrapper = render(createTable({ data: localData })); + const wrapper = render(createTable({ data })); + expect(wrapper).toMatchSnapshot(); + }); + + it('renders fixed column correctly', () => { + const columns = [ + { title: 'Name', dataIndex: 'name', key: 'name', fixed: true }, + { title: 'Age', dataIndex: 'age', key: 'age' }, + { title: 'Gender', dataIndex: 'gender', key: 'gender', fixed: 'right' }, + ]; + const data = [ + { key: 0, name: 'Lucy', age: 27, gender: 'F' }, + { key: 1, name: 'Jack', age: 28, gender: 'M' }, + ]; + const wrapper = render(createTable({ columns, data, expandedRowRender })); expect(wrapper).toMatchSnapshot(); }); @@ -107,7 +124,7 @@ describe('Table.expand', () => { expandedRowClassName, })); expect(wrapper).toMatchSnapshot(); - expect(expandedRowClassName).toBeCalledWith(data[0], 0, 0); + expect(expandedRowClassName).toBeCalledWith(sampleData[0], 0, 0); }); it('fires expand change event', () => { @@ -117,9 +134,9 @@ describe('Table.expand', () => { onExpand, })); wrapper.find('ExpandIcon').first().simulate('click'); - expect(onExpand).toBeCalledWith(true, data[0]); + expect(onExpand).toBeCalledWith(true, sampleData[0]); wrapper.find('ExpandIcon').first().simulate('click'); - expect(onExpand).toBeCalledWith(false, data[0]); + expect(onExpand).toBeCalledWith(false, sampleData[0]); }); it('fires onExpandedRowsChange event', () => { @@ -145,7 +162,7 @@ describe('Table.expand', () => { expect(onExpandedRowsChange).toBeCalledWith([1]); }); - fit('expand row by click', () => { + it('expand row by click', () => { const wrapper = mount(createTable({ expandedRowRender })); wrapper.find('ExpandIcon').first().simulate('click'); expect(wrapper.render()).toMatchSnapshot(); diff --git a/tests/__snapshots__/Table.expandRow.spec.js.snap b/tests/__snapshots__/Table.expandRow.spec.js.snap index e1283e60e..0317a57d3 100644 --- a/tests/__snapshots__/Table.expandRow.spec.js.snap +++ b/tests/__snapshots__/Table.expandRow.spec.js.snap @@ -1,4688 +1,210 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Table.expand controlled by expandedRowKeys 1`] = ` -
- - - -
+
+ + + + + + + + + -
- - -
- - -
+ Name + + Age +
- - - - - - - - - - - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 28, - "key": 1, - "name": "Jack", - } - } - > - - - - - - - - - - - - - - - - - - - - -
- Name - - Age -
- - - - - Lucy - - 27 -
-

- extra data -

-
- - - - - Jack - - 28 -
- - -
- - - - - - - + + + Lucy + + + 27 + + + + +

+ extra data +

+ + + + + + + Jack + + + 28 + + + + + + + `; exports[`Table.expand controlled by expandedRowKeys 2`] = ` - - - - -
+
+ + + + + + + + + -
- - -
- - -
+ Name + + Age +
- - - - - - - - - - - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={0} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 27, - "key": 0, - "name": "Lucy", - } - } - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - indent={0} - indentSize={15} - index={1} - key="name" - prefixCls="rc-table-row" - record={ - Object { - "age": 28, - "key": 1, - "name": "Jack", - } - } - > - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Name - - Age -
- - - - - Lucy - - 27 -
-

- extra data -

-
- - - - - Jack - - 28 -
-

- extra data -

-
- - - - - - - - - - + + + Lucy + + + 27 + + + + +

+ extra data +

+ + + + + + + Jack + + + 28 + + + + +

+ extra data +

+ + + + + + + `; exports[`Table.expand expand all rows by default 1`] = ` @@ -4841,7 +363,7 @@ exports[`Table.expand expand row by click 1`] = ` style="padding-left: 0px;" /> Lucy @@ -4853,6 +375,7 @@ exports[`Table.expand expand row by click 1`] = ` `; +exports[`Table.expand renders fixed column correctly 1`] = ` +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Name + + Age + + Gender +
+ + + Lucy + + 27 + + F +
+ + + Jack + + 28 + + M +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
+ Name +
+ + + Lucy +
+ + + Jack +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
+ Gender +
+ F +
+ M +
+
+
+
+
+
+`; + exports[`Table.expand renders nested data correctly 1`] = `
Date: Mon, 23 Oct 2017 16:13:20 +0800 Subject: [PATCH 26/26] Fix expand row height sync --- src/ExpandableTable.js | 1 + src/TableRow.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ExpandableTable.js b/src/ExpandableTable.js index fd42721a7..797b49817 100644 --- a/src/ExpandableTable.js +++ b/src/ExpandableTable.js @@ -156,6 +156,7 @@ class ExpandableTable extends React.Component { ancestorKeys={ancestorKeys} prefixCls={`${prefixCls}-expanded-row`} indent={1} + fixed={fixed} /> ); } diff --git a/src/TableRow.js b/src/TableRow.js index d26d0ac7a..92fea8ae2 100644 --- a/src/TableRow.js +++ b/src/TableRow.js @@ -187,7 +187,6 @@ function getRowHeight(state, props) { return null; } - if (expandedRowsHeight[rowKey]) { return expandedRowsHeight[rowKey]; }