diff --git a/docs/demo/expandedRowSpan.md b/docs/demo/expandedRowSpan.md new file mode 100644 index 00000000..046c3f8b --- /dev/null +++ b/docs/demo/expandedRowSpan.md @@ -0,0 +1,8 @@ +--- +title: expandedRowSpan +nav: + title: Demo + path: /demo +--- + + diff --git a/docs/examples/expandedRowSpan.tsx b/docs/examples/expandedRowSpan.tsx new file mode 100644 index 00000000..5aeba748 --- /dev/null +++ b/docs/examples/expandedRowSpan.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import Table from 'rc-table'; +import '../../assets/index.less'; +import type { ColumnsType } from '@/interface'; + +const columns: ColumnsType = [ + { + title: '手机号', + dataIndex: 'a', + colSpan: 2, + width: 100, + onCell: (_, index) => { + const props: React.TdHTMLAttributes = {}; + if (index === 0) props.rowSpan = 1; + if (index === 1) props.rowSpan = 4; + if (index === 2) props.rowSpan = 0; + if (index === 3) props.rowSpan = 0; + if (index === 4) props.rowSpan = 0; + if (index === 5) props.rowSpan = undefined; + return props; + }, + }, + { title: '电话', dataIndex: 'b', colSpan: 0, width: 100 }, + Table.EXPAND_COLUMN, + { title: 'Name', dataIndex: 'c', width: 100 }, + { title: 'Address', dataIndex: 'd', width: 200 }, +]; + +const data = [ + { a: '12313132132', b: '0571-43243256', c: '小二', d: '文零西路', e: 'Male', key: 'z' }, + { a: '13812340987', b: '0571-12345678', c: '张三', d: '文一西路', e: 'Male', key: 'a' }, + { a: '13812340987', b: '0571-12345678', c: '张夫人', d: '文一西路', e: 'Female', key: 'b' }, + { a: '13812340987', b: '0571-099877', c: '李四', d: '文二西路', e: 'Male', key: 'c' }, + { a: '13812340987', b: '0571-099877', c: '李四', d: '文二西路', e: 'Male', key: 'd' }, + { a: '1381200008888', b: '0571-099877', c: '王五', d: '文二西路', e: 'Male', key: 'e' }, +]; + +const Demo = () => ( +
+

expanded & rowSpan

+ > + rowKey="key" + columns={columns} + data={data} + expandable={{ expandedRowRender: record =>

{record.key}

}} + className="table" + /> +
+); + +export default Demo; diff --git a/src/Body/BodyRow.tsx b/src/Body/BodyRow.tsx index 46ca866f..cd76493c 100644 --- a/src/Body/BodyRow.tsx +++ b/src/Body/BodyRow.tsx @@ -19,6 +19,7 @@ export interface BodyRowProps { scopeCellComponent: CustomizeComponent; indent?: number; rowKey: React.Key; + rowKeys: React.Key[]; } // ================================================================================== @@ -30,6 +31,7 @@ export function getCellProps( colIndex: number, indent: number, index: number, + rowKeys: React.Key[], ) { const { record, @@ -43,6 +45,8 @@ export function getCellProps( expanded, hasNestChildren, onTriggerExpand, + expandable, + expandedKeys, } = rowInfo; const key = columnsKey[colIndex]; @@ -71,6 +75,21 @@ export function getCellProps( let additionalCellProps: React.TdHTMLAttributes; if (column.onCell) { additionalCellProps = column.onCell(record, index); + const { rowSpan } = additionalCellProps; + + // For expandable row with rowSpan, + // We should increase the rowSpan if the row is expanded + if (expandable) { + let currentRowSpan = rowSpan; + + for (let i = index; i < index + rowSpan; i += 1) { + const rowKey = rowKeys[i]; + if (expandedKeys.has(rowKey)) { + currentRowSpan += 1; + } + } + additionalCellProps.rowSpan = currentRowSpan; + } } return { @@ -102,8 +121,10 @@ function BodyRow( rowComponent: RowComponent, cellComponent, scopeCellComponent, + rowKeys, } = props; const rowInfo = useRowInfo(record, rowKey, index, indent); + const { prefixCls, flattenColumns, @@ -153,6 +174,7 @@ function BodyRow( colIndex, indent, index, + rowKeys, ); return ( diff --git a/src/Body/index.tsx b/src/Body/index.tsx index aec12e9d..d6e4d8e4 100644 --- a/src/Body/index.tsx +++ b/src/Body/index.tsx @@ -42,8 +42,14 @@ function Body(props: BodyProps) { 'emptyNode', ]); - const flattenData: { record: RecordType; indent: number; index: number }[] = - useFlattenRecords(data, childrenColumnName, expandedKeys, getRowKey); + const flattenData = useFlattenRecords( + data, + childrenColumnName, + expandedKeys, + getRowKey, + ); + + const rowKeys = React.useMemo(() => flattenData.map(item => item.rowKey), [flattenData]); // =================== Performance ==================== const perfRef = React.useRef({ @@ -59,14 +65,13 @@ function Body(props: BodyProps) { let rows: React.ReactNode; if (data.length) { rows = flattenData.map((item, idx) => { - const { record, indent, index: renderIndex } = item; - - const key = getRowKey(record, idx); + const { record, indent, index: renderIndex, rowKey } = item; return ( (props: VirtualCellProps) { colIndex, indent, index, + [], ); const { style: cellStyle, colSpan = 1, rowSpan = 1 } = additionalCellProps; diff --git a/src/hooks/useFlattenRecords.ts b/src/hooks/useFlattenRecords.ts index ff67f5d9..bd5e0c54 100644 --- a/src/hooks/useFlattenRecords.ts +++ b/src/hooks/useFlattenRecords.ts @@ -15,6 +15,7 @@ function fillRecords( record, indent, index, + rowKey: getRowKey(record, index), }); const key = getRowKey(record); @@ -41,6 +42,7 @@ export interface FlattenData { record: RecordType; indent: number; index: number; + rowKey: Key; } /** @@ -80,6 +82,7 @@ export default function useFlattenRecords( record: item, indent: 0, index, + rowKey: getRowKey(item, index), }; }); }, [data, childrenColumnName, expandedKeys, getRowKey]);