From 881f14984a968e1132066cf0d3bfe3a7fe96197c Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Sun, 21 Aug 2016 04:56:04 +0800 Subject: [PATCH 1/3] grouping columns --- examples/grouping-columns.html | 0 examples/grouping-columns.js | 99 ++++++++++++++++++++++++++++++++++ src/Table.jsx | 91 +++++++++++++++++++++++++++---- tests/GroupingColumns.spec.js | 86 +++++++++++++++++++++++++++++ tests/index.js | 1 + 5 files changed, 266 insertions(+), 11 deletions(-) create mode 100644 examples/grouping-columns.html create mode 100644 examples/grouping-columns.js create mode 100644 tests/GroupingColumns.spec.js diff --git a/examples/grouping-columns.html b/examples/grouping-columns.html new file mode 100644 index 000000000..e69de29bb diff --git a/examples/grouping-columns.js b/examples/grouping-columns.js new file mode 100644 index 000000000..095286a04 --- /dev/null +++ b/examples/grouping-columns.js @@ -0,0 +1,99 @@ +/* eslint-disable no-console,func-names,react/no-multi-comp */ +const React = require('react'); +const ReactDOM = require('react-dom'); +const Table = require('rc-table'); +require('rc-table/assets/index.less'); + +const columns = [ + { + title: '姓名', + dataIndex: 'name', + key: 'name', + }, + { + title: '其它', + children: [ + { + title: '年龄', + dataIndex: 'age', + key: 'age', + }, + { + title: '住址', + children: [ + { + title: '街道', + dataIndex: 'street', + key: 'street', + }, + { + title: '小区', + children: [ + { + title: '单元', + dataIndex: 'building', + key: 'building', + }, + { + title: '门牌', + dataIndex: 'number', + key: 'number', + }, + ], + }, + ], + }, + ], + }, + { + title: '公司', + children: [ + { + title: '地址', + dataIndex: 'companyAddress', + key: 'companyAddress', + }, + { + title: '名称', + dataIndex: 'companyName', + key: 'companyName', + }, + ], + }, + { + title: '性别', + dataIndex: 'gender', + key: 'gender', + }, +]; + + +const data = [{ + key: '1', + name: '胡彦斌', + age: 32, + street: '拱墅区和睦街道', + building: 1, + number: 2033, + companyAddress: '西湖区湖底公园', + companyName: '湖底有限公司', + gender: '男', +}, { + key: '2', + name: '胡彦祖', + age: 42, + street: '拱墅区和睦街道', + building: 3, + number: 2035, + companyAddress: '西湖区湖底公园', + companyName: '湖底有限公司', + gender: '男', +}]; + +ReactDOM.render( +
+

grouping columns

+ + , + document.getElementById('__react-content') +); diff --git a/src/Table.jsx b/src/Table.jsx index 76209b08a..40b5bb53c 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -189,30 +189,80 @@ const Table = React.createClass({ getHeader(columns, fixed) { const { showHeader, expandIconAsCell, prefixCls } = this.props; - let ths = []; + let finalColumns = []; if (expandIconAsCell && fixed !== 'right') { - ths.push({ + finalColumns.push({ key: 'rc-table-expandIconAsCell', className: `${prefixCls}-expand-icon-th`, title: '', }); } - ths = ths.concat(columns || this.getCurrentColumns()).map(c => { - if (c.colSpan !== 0) { - return ; - } - }); + finalColumns = finalColumns.concat(columns || this.getCurrentColumns()); + const rows = this.getHeaderRows(finalColumns); + const { fixedColumnsHeadRowsHeight } = this.state; const trStyle = (fixedColumnsHeadRowsHeight[0] && columns) ? { height: fixedColumnsHeadRowsHeight[0], } : null; return showHeader ? ( - {ths} + {rows.map(r => { + r.children = r.children.map(c => ; + })} ) : null; }, + getHeaderRows(columns, currentRow = 0, parentCell = null, rows = []) { + if (!rows[currentRow]) { + rows[currentRow] = { + key: currentRow, + children: [], + }; + } + let currentCol = rows[currentRow].children.length; + const setRowSpan = cell => { + const rowSpan = rows.length - currentRow; + if (cell && !cell.hasChildren && rowSpan !== 1 && (!cell.rowSpan || cell.rowSpan < rowSpan)) { + cell.rowSpan = rowSpan; + } + }; + columns.forEach((column, index) => { + const cell = { + key: column.key, + className: column.className || '', + children: column.title, + }; + if (column.children && column.children.length > 0) { + cell.hasChildren = true; + this.getHeaderRows(column.children, currentRow + 1, cell, rows); + if (parentCell) { + parentCell.colSpan = parentCell.colSpan || 0; + parentCell.colSpan = parentCell.colSpan + cell.colSpan; + } + } else { + if (parentCell) { + parentCell.colSpan = parentCell.colSpan || 0; + parentCell.colSpan++; + } + } + const prevCell = rows[currentRow].children[currentCol - 1]; + setRowSpan(prevCell); + if (index + 1 === columns.length) { + setRowSpan(cell); + } + if ('colSpan' in column) { + cell.colSpan = column.colSpan; + } + if (cell.colSpan !== 0) { + rows[currentRow].children.push(cell); + } + currentCol++; + }); + return rows; + }, + getExpandedRow(key, content, visible, className, fixed) { const prefixCls = this.props.prefixCls; return ( @@ -224,7 +274,7 @@ const Table = React.createClass({ {(this.props.expandIconAsCell && fixed !== 'right') ? @@ -271,6 +321,8 @@ const Table = React.createClass({ height: fixedColumnsBodyRowsHeight[i], } : {}; + const leafColumns = this.getLeafColumns(columns || this.getCurrentColumns()); + rst.push( ); } - cols = cols.concat((columns || this.props.columns).map(c => { + const leafColumns = this.getLeafColumns(columns || this.props.columns); + cols = cols.concat(leafColumns.map(c => { return ; })); return {cols}; @@ -517,6 +570,22 @@ const Table = React.createClass({ return Math.ceil((columnsPageRange[1] - columnsPageRange[0] + 1) / columnsPageSize) - 1; }, + getLeafColumns(columns) { + const leafColumns = []; + columns.forEach(column => { + if (!column.children) { + leafColumns.push(column); + } else { + leafColumns.push(...this.getLeafColumns(column.children)); + } + }); + return leafColumns; + }, + + getLeafColumnsCount(columns) { + return this.getLeafColumns(columns).length; + }, + goToColumnsPage(currentColumnsPage) { const maxColumnsPage = this.getMaxColumnsPage(); let page = currentColumnsPage; diff --git a/tests/GroupingColumns.spec.js b/tests/GroupingColumns.spec.js new file mode 100644 index 000000000..df7fe6269 --- /dev/null +++ b/tests/GroupingColumns.spec.js @@ -0,0 +1,86 @@ +/* eslint-disable no-console,func-names,react/no-multi-comp */ +const expect = require('expect.js'); +const Table = require('../'); +const React = require('react'); +const ReactDOM = require('react-dom'); +const $ = require('jquery'); + +describe('Table with grouping columns', () => { + const div = document.createElement('div'); + + /** + * +---+---------------+-------+---+ + * | | B | I | | + * | +---+---------------+---+ | + * | | | D | | | | + * | A | +---+-------+ | | L | + * | | C | E | F | J | K | | + * | | | +---+---+ | | | + * | | | | G | H | | | | + * +---+---+---+---+---+---+---+---+ + */ + const columns = [ + { title: '表头A', className: 'title-a', dataIndex: 'a', key: 'a' }, + { title: '表头B', className: 'title-b', children: + [ + { title: '表头C', className: 'title-c', dataIndex: 'b', key: 'b' }, + { title: '表头D', className: 'title-d', children: + [ + { title: '表头E', className: 'title-e', dataIndex: 'c', key: 'c' }, + { title: '表头F', className: 'title-f', children: + [ + { title: '表头G', className: 'title-g', dataIndex: 'd', key: 'd' }, + { title: '表头H', className: 'title-h', dataIndex: 'e', key: 'e' }, + ], + }, + ], + }, + ], + }, + { title: '表头I', className: 'title-i', children: + [ + { title: '表头J', className: 'title-j', dataIndex: 'f', key: 'f' }, + { title: '表头K', className: 'title-k', dataIndex: 'g', key: 'g' }, + ], + }, + { title: '表头L', className: 'title-l', dataIndex: 'h', key: 'h' }, + ]; + + const data = [ + { key: '1', a: 'a1', b: 'b1', c: 'c1' }, + { key: '2', a: 'a2', b: 'b2', c: 'c2' }, + { key: '3', a: 'a3', b: 'b3', c: 'c3' }, + ]; + + let node; + + beforeEach(() => { + ReactDOM.render( +
{c.title}
); + return
: null} - + {fixed !== 'right' ? content : ' '}
, + div + ); + node = $(div); + }); + + it('group columns', () => { + const cells = { + 'title-a': ['4', undefined], + 'title-b': [undefined, '4'], + 'title-c': ['3', undefined], + 'title-d': [undefined, '3'], + 'title-e': ['2', undefined], + 'title-f': [undefined, '2'], + 'title-g': [undefined, undefined], + 'title-h': [undefined, undefined], + 'title-i': [undefined, '2'], + 'title-j': ['3', undefined], + 'title-k': ['3', undefined], + 'title-l': ['4', undefined], + }; + Object.keys(cells).forEach(className => { + const cell = cells[className]; + expect(node.find(`.${className}`).attr('rowspan')).to.be(cell[0]); + expect(node.find(`.${className}`).attr('colspan')).to.be(cell[1]); + }); + }); +}); diff --git a/tests/index.js b/tests/index.js index de1faaea5..5f1d842d2 100644 --- a/tests/index.js +++ b/tests/index.js @@ -1,2 +1,3 @@ require('./index.spec.js'); require('./PagingColumns.spec.js'); +require('./GroupingColumns.spec.js'); From e4a2b11f19668f67a60ad192e9570053f170de37 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Tue, 23 Aug 2016 13:28:08 +0800 Subject: [PATCH 2/3] work with fixed columns --- assets/index.less | 22 ++++- src/Table.jsx | 111 +++++++++++++++---------- tests/GroupingColumns.spec.js | 149 +++++++++++++++++++++------------- 3 files changed, 178 insertions(+), 104 deletions(-) diff --git a/assets/index.less b/assets/index.less index a557042e3..5e1559929 100644 --- a/assets/index.less +++ b/assets/index.less @@ -1,15 +1,20 @@ @tablePrefixCls: rc-table; @text-color : #666; @font-size-base : 12px; +@line-height: 1.5; @table-border-color: #e9e9e9; @table-head-background-color: #f3f3f3; +@vertical-padding: 16px; +@horizontal-padding: 8px; +@row-height: @font-size-base * @line-height + @vertical-padding * 2; + .@{tablePrefixCls} { font-size: @font-size-base; color: @text-color; transition: opacity 0.3s ease; position: relative; - line-height: 1.5; + line-height: @line-height; overflow: hidden; .@{tablePrefixCls}-scroll { @@ -40,7 +45,7 @@ } .@{tablePrefixCls}-title { - padding: 16px 8px; + padding: @vertical-padding @horizontal-padding; border-top: 1px solid #e9e9e9; } @@ -49,7 +54,7 @@ } .@{tablePrefixCls}-footer { - padding: 16px 8px; + padding: @vertical-padding @horizontal-padding; border-bottom: 1px solid #e9e9e9; } @@ -81,7 +86,7 @@ } th, td { - padding: 16px 8px; + padding: @vertical-padding @horizontal-padding; } } @@ -164,6 +169,15 @@ width: auto; background: #fff; } + + .generate-rowspan(10); + + .generate-rowspan(@n, @i: 1) when (@i =< @n) { + th.@{tablePrefixCls}-rowspan-@{i} { + height: @row-height * @i - @vertical-padding * 2; + } + .generate-rowspan(@n, (@i + 1)); + } } &-fixed-left { diff --git a/src/Table.jsx b/src/Table.jsx index 40b5bb53c..7cce3bf7a 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -189,16 +189,21 @@ const Table = React.createClass({ getHeader(columns, fixed) { const { showHeader, expandIconAsCell, prefixCls } = this.props; - let finalColumns = []; + let rows; + if (columns) { + rows = this.getHeaderRows(columns); + } else { + rows = this.getHeaderRows(this.groupColumns(this.getCurrentColumns())); + } + if (expandIconAsCell && fixed !== 'right') { - finalColumns.push({ + rows[0].unshift({ key: 'rc-table-expandIconAsCell', - className: `${prefixCls}-expand-icon-th`, + className: `${prefixCls}-expand-icon-th ${prefixCls}-rowspan-${rows.length}`, title: '', + rowSpan: rows.length, }); } - finalColumns = finalColumns.concat(columns || this.getCurrentColumns()); - const rows = this.getHeaderRows(finalColumns); const { fixedColumnsHeadRowsHeight } = this.state; const trStyle = (fixedColumnsHeadRowsHeight[0] && columns) ? { @@ -206,59 +211,44 @@ const Table = React.createClass({ } : null; return showHeader ? ( - {rows.map(r => { - r.children = r.children.map(c => ; + {rows.map((r, i) => { + const ths = r.map(c => ; })} ) : null; }, - getHeaderRows(columns, currentRow = 0, parentCell = null, rows = []) { - if (!rows[currentRow]) { - rows[currentRow] = { - key: currentRow, - children: [], - }; - } - let currentCol = rows[currentRow].children.length; - const setRowSpan = cell => { - const rowSpan = rows.length - currentRow; - if (cell && !cell.hasChildren && rowSpan !== 1 && (!cell.rowSpan || cell.rowSpan < rowSpan)) { - cell.rowSpan = rowSpan; + getHeaderRows(columns, currentRow = 0, rows) { + const { prefixCls } = this.props; + + rows = rows || []; + rows[currentRow] = rows[currentRow] || []; + + columns.forEach(column => { + if (column.rowSpan && rows.length < column.rowSpan) { + while (rows.length < column.rowSpan) { + rows.push([]); + } } - }; - columns.forEach((column, index) => { const cell = { key: column.key, className: column.className || '', children: column.title, }; - if (column.children && column.children.length > 0) { - cell.hasChildren = true; - this.getHeaderRows(column.children, currentRow + 1, cell, rows); - if (parentCell) { - parentCell.colSpan = parentCell.colSpan || 0; - parentCell.colSpan = parentCell.colSpan + cell.colSpan; - } - } else { - if (parentCell) { - parentCell.colSpan = parentCell.colSpan || 0; - parentCell.colSpan++; - } - } - const prevCell = rows[currentRow].children[currentCol - 1]; - setRowSpan(prevCell); - if (index + 1 === columns.length) { - setRowSpan(cell); + 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; + cell.className += ` ${prefixCls}-rowspan-${cell.rowSpan}`; + } if (cell.colSpan !== 0) { - rows[currentRow].children.push(cell); + rows[currentRow].push(cell); } - currentCol++; }); return rows; }, @@ -414,7 +404,7 @@ const Table = React.createClass({ getLeftFixedTable() { const { columns } = this.props; - const fixedColumns = columns.filter( + const fixedColumns = this.groupColumns(columns).filter( column => column.fixed === 'left' || column.fixed === true ); return this.getTable({ @@ -425,7 +415,7 @@ const Table = React.createClass({ getRightFixedTable() { const { columns } = this.props; - const fixedColumns = columns.filter(column => column.fixed === 'right'); + const fixedColumns = this.groupColumns(columns).filter(column => column.fixed === 'right'); return this.getTable({ columns: fixedColumns, fixed: 'right', @@ -600,6 +590,41 @@ const Table = React.createClass({ }); }, + groupColumns(columns, currentRow = 0, parentColumn = {}, rows = []) { + if (!~rows.indexOf(currentRow)) { + rows.push(currentRow); + } + const grouped = []; + const setRowSpan = column => { + const rowSpan = rows.length - currentRow; + if (column && + !column.children && + rowSpan > 1 && + (!column.rowSpan || column.rowSpan < rowSpan) + ) { + column.rowSpan = rowSpan; + } + }; + columns.forEach((column, index) => { + const newColumn = { ...column }; + parentColumn.colSpan = parentColumn.colSpan || 0; + if (newColumn.children && newColumn.children.length > 0) { + newColumn.children = this.groupColumns(newColumn.children, currentRow + 1, newColumn, rows); + parentColumn.colSpan = parentColumn.colSpan + newColumn.colSpan; + } else { + parentColumn.colSpan++; + } + for (let i = 0; i < index; ++i) { + setRowSpan(grouped[i]); + } + if (index + 1 === columns.length) { + setRowSpan(newColumn); + } + grouped.push(newColumn); + }); + return grouped; + }, + syncFixedTableRowHeight() { const { prefixCls } = this.props; const headRows = this.refs.headTable ? this.refs.headTable.querySelectorAll(`tr`) : []; diff --git a/tests/GroupingColumns.spec.js b/tests/GroupingColumns.spec.js index df7fe6269..6e01f2eaf 100644 --- a/tests/GroupingColumns.spec.js +++ b/tests/GroupingColumns.spec.js @@ -6,76 +6,79 @@ const ReactDOM = require('react-dom'); const $ = require('jquery'); describe('Table with grouping columns', () => { - const div = document.createElement('div'); + let div; + let node; - /** - * +---+---------------+-------+---+ - * | | B | I | | - * | +---+---------------+---+ | - * | | | D | | | | - * | A | +---+-------+ | | L | - * | | C | E | F | J | K | | - * | | | +---+---+ | | | - * | | | | G | H | | | | - * +---+---+---+---+---+---+---+---+ - */ - const columns = [ - { title: '表头A', className: 'title-a', dataIndex: 'a', key: 'a' }, - { title: '表头B', className: 'title-b', children: - [ - { title: '表头C', className: 'title-c', dataIndex: 'b', key: 'b' }, - { title: '表头D', className: 'title-d', children: - [ - { title: '表头E', className: 'title-e', dataIndex: 'c', key: 'c' }, - { title: '表头F', className: 'title-f', children: - [ - { title: '表头G', className: 'title-g', dataIndex: 'd', key: 'd' }, - { title: '表头H', className: 'title-h', dataIndex: 'e', key: 'e' }, - ], - }, - ], - }, - ], - }, - { title: '表头I', className: 'title-i', children: - [ - { title: '表头J', className: 'title-j', dataIndex: 'f', key: 'f' }, - { title: '表头K', className: 'title-k', dataIndex: 'g', key: 'g' }, - ], - }, - { title: '表头L', className: 'title-l', dataIndex: 'h', key: 'h' }, - ]; + beforeEach(() => { + div = document.createElement('div'); + node = $(div); + }); - const data = [ - { key: '1', a: 'a1', b: 'b1', c: 'c1' }, - { key: '2', a: 'a2', b: 'b2', c: 'c2' }, - { key: '3', a: 'a3', b: 'b3', c: 'c3' }, - ]; + it('group columns', () => { + /** + * +---+---+---------------+-------+---+ + * | | | C | J | | + * | | +---+---------------+---+ | + * | | | | E | | | | + * | A | B | +---+-------+ | | M | + * | | | D | F | G | K | L | | + * | | | | +---+---+ | | | + * | | | | | H | I | | | | + * +---+---+---+---+---+---+---+---+---+ + */ + const columns = [ + { title: '表头A', className: 'title-a', dataIndex: 'a', key: 'a' }, + { title: '表头B', className: 'title-b', dataIndex: 'b', key: 'b' }, + { title: '表头C', className: 'title-c', children: + [ + { title: '表头D', className: 'title-d', dataIndex: 'c', key: 'c' }, + { title: '表头E', className: 'title-e', children: + [ + { title: '表头F', className: 'title-f', dataIndex: 'd', key: 'd' }, + { title: '表头G', className: 'title-g', children: + [ + { title: '表头H', className: 'title-h', dataIndex: 'e', key: 'e' }, + { title: '表头I', className: 'title-i', dataIndex: 'f', key: 'f' }, + ], + }, + ], + }, + ], + }, + { title: '表头J', className: 'title-j', children: + [ + { title: '表头K', className: 'title-k', dataIndex: 'g', key: 'g' }, + { title: '表头L', className: 'title-l', dataIndex: 'h', key: 'h' }, + ], + }, + { title: '表头M', className: 'title-m', dataIndex: 'i', key: 'i' }, + ]; - let node; + const data = [ + { key: '1', a: 'a1', b: 'b1', c: 'c1', d: 'd1', e: 'e1', f: 'f1', g: 'g1', h: 'h1', i: 'i1' }, + { key: '2', a: 'a2', b: 'b2', c: 'c2', d: 'd2', e: 'e2', f: 'f2', g: 'g2', h: 'h2', i: 'i2' }, + { key: '3', a: 'a3', b: 'b3', c: 'c3', d: 'd3', e: 'e3', f: 'f3', g: 'g3', h: 'h3', i: 'i3' }, + ]; - beforeEach(() => { ReactDOM.render(
); - return
); + return
, div ); - node = $(div); - }); - it('group columns', () => { const cells = { 'title-a': ['4', undefined], - 'title-b': [undefined, '4'], - 'title-c': ['3', undefined], - 'title-d': [undefined, '3'], - 'title-e': ['2', undefined], - 'title-f': [undefined, '2'], - 'title-g': [undefined, undefined], + 'title-b': ['4', undefined], + 'title-c': [undefined, '4'], + 'title-d': ['3', undefined], + 'title-e': [undefined, '3'], + 'title-f': ['2', undefined], + 'title-g': [undefined, '2'], 'title-h': [undefined, undefined], - 'title-i': [undefined, '2'], - 'title-j': ['3', undefined], + 'title-i': [undefined, undefined], + 'title-j': [undefined, '2'], 'title-k': ['3', undefined], - 'title-l': ['4', undefined], + 'title-l': ['3', undefined], + 'title-m': ['4', undefined], }; Object.keys(cells).forEach(className => { const cell = cells[className]; @@ -83,4 +86,36 @@ describe('Table with grouping columns', () => { expect(node.find(`.${className}`).attr('colspan')).to.be(cell[1]); }); }); + + it('work with fixed columns', () => { + const columns = [ + { title: '表头A', className: 'title-a', dataIndex: 'a', key: 'a', fixed: 'left' }, + { title: '表头B', className: 'title-b', children: + [ + { title: '表头C', className: 'title-c', dataIndex: 'b', key: 'b' }, + { title: '表头D', className: 'title-d', dataIndex: 'c', key: 'c' }, + ], + }, + { title: '表头E', className: 'title-e', dataIndex: 'd', key: 'd', fixed: 'right' }, + ]; + + const data = [ + { key: '1', a: 'a1', b: 'b1', c: 'c1', d: 'd1' }, + { key: '2', a: 'a2', b: 'b2', c: 'c2', d: 'd2' }, + { key: '3', a: 'a3', b: 'b3', c: 'c3', d: 'd3' }, + ]; + + ReactDOM.render( +
, + div + ); + + const titleA = node.find('.rc-table-fixed-left .title-a'); + const titleE = node.find('.rc-table-fixed-right .title-e'); + + expect(titleA.attr('rowspan')).to.be('2'); + expect(titleA.hasClass('rc-table-rowspan-2')).to.be(true); + expect(titleE.attr('rowspan')).to.be('2'); + expect(titleE.hasClass('rc-table-rowspan-2')).to.be(true); + }); }); From 0191cbac286491c20b5b7ff5a3f5bdbf9ce18662 Mon Sep 17 00:00:00 2001 From: Wei Zhu Date: Tue, 23 Aug 2016 15:04:43 +0800 Subject: [PATCH 3/3] add some comments --- src/Table.jsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Table.jsx b/src/Table.jsx index 7cce3bf7a..9a582e349 100644 --- a/src/Table.jsx +++ b/src/Table.jsx @@ -191,6 +191,7 @@ const Table = React.createClass({ const { showHeader, expandIconAsCell, prefixCls } = this.props; let rows; if (columns) { + // columns are passed from fixed table function that already grouped. rows = this.getHeaderRows(columns); } else { rows = this.getHeaderRows(this.groupColumns(this.getCurrentColumns())); @@ -590,7 +591,9 @@ const Table = React.createClass({ }); }, + // add appropriate rowspan and colspan to column groupColumns(columns, currentRow = 0, parentColumn = {}, rows = []) { + // track how many rows we got if (!~rows.indexOf(currentRow)) { rows.push(currentRow); } @@ -598,7 +601,7 @@ const Table = React.createClass({ const setRowSpan = column => { const rowSpan = rows.length - currentRow; if (column && - !column.children && + !column.children && // parent columns are supposed to be one row rowSpan > 1 && (!column.rowSpan || column.rowSpan < rowSpan) ) { @@ -614,9 +617,11 @@ const Table = React.createClass({ } else { parentColumn.colSpan++; } + // update rowspan to all previous columns for (let i = 0; i < index; ++i) { setRowSpan(grouped[i]); } + // last column, update rowspan immediately if (index + 1 === columns.length) { setRowSpan(newColumn); }