diff --git a/components/table/__tests__/__snapshots__/demo.test.js.snap b/components/table/__tests__/__snapshots__/demo.test.js.snap index fc622f90c4..214adadebd 100755 --- a/components/table/__tests__/__snapshots__/demo.test.js.snap +++ b/components/table/__tests__/__snapshots__/demo.test.js.snap @@ -12220,6 +12220,396 @@ exports[`renders ./components/table/demo/row-selection-custom.md correctly 1`] = `; +exports[`renders ./components/table/demo/row-selection-custom-debug.md correctly 1`] = ` +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ Name +
+ false: + + + Edward King 0 +
+ Another Row +
+ false: + + + Edward King 2 +
+ Another Row +
+ false: + + + Edward King 4 +
+ Another Row +
+ false: + + + Edward King 6 +
+ Another Row +
+ false: + + + Edward King 8 +
+ Another Row +
+
+
+
+ +
+
+
+`; + exports[`renders ./components/table/demo/size.md correctly 1`] = `

diff --git a/components/table/demo/row-selection-custom-debug.md b/components/table/demo/row-selection-custom-debug.md new file mode 100644 index 0000000000..82d212c1d6 --- /dev/null +++ b/components/table/demo/row-selection-custom-debug.md @@ -0,0 +1,50 @@ +--- +order: 99 +title: + en-US: Custom selection group + zh-CN: 自定义选择项组 +debug: true +--- + +## zh-CN + +自定义选项分组。 + +## en-US + +Customize selection group. + +```jsx +import { Table } from 'antd'; + +const columns = [ + { + title: 'Name', + dataIndex: 'name', + }, +]; + +const data = []; +for (let i = 0; i < 46; i++) { + data.push({ + key: i, + name: i % 2 === 0 ? `Edward King ${i}` : 'Another Row', + }); +} + +const App = () => { + const rowSelection = { + renderCell: (checked, record, index, node) => ({ + props: { rowSpan: index % 2 === 0 ? 2 : 0 }, + children: ( + <> + {String(checked)}: {node} + + ), + }), + }; + return ; +}; + +ReactDOM.render(, mountNode); +``` diff --git a/components/table/hooks/useSelection.tsx b/components/table/hooks/useSelection.tsx index 3093f984ce..1f46d26071 100644 --- a/components/table/hooks/useSelection.tsx +++ b/components/table/hooks/useSelection.tsx @@ -76,6 +76,7 @@ export default function useSelection( type: selectionType, selections, fixed, + renderCell: customizeRenderCell, } = rowSelection || {}; const { locale = defaultLocale } = React.useContext(ConfigContext); @@ -305,111 +306,132 @@ export default function useSelection( } // Body Cell - let renderCell: (_: RecordType, record: RecordType, index: number) => React.ReactNode; + let renderCell: ( + _: RecordType, + record: RecordType, + index: number, + ) => { node: React.ReactNode; checked: boolean }; if (selectionType === 'radio') { renderCell = (_, record, index) => { const key = getRowKey(record, index); - - return ( - { - if (!keySet.has(key)) { - triggerSingleSelection(key, true, [key], event.nativeEvent); - } - }} - /> - ); + const checked = keySet.has(key); + + return { + node: ( + { + if (!keySet.has(key)) { + triggerSingleSelection(key, true, [key], event.nativeEvent); + } + }} + /> + ), + checked, + }; }; } else { renderCell = (_, record, index) => { const key = getRowKey(record, index); - const hasKey = keySet.has(key); + const checked = keySet.has(key); // Record checked - return ( - { - const { shiftKey } = nativeEvent; - - let startIndex: number = -1; - let endIndex: number = -1; - - // Get range of this - if (shiftKey) { - const pointKeys = new Set([lastSelectedKey, key]); - - recordKeys.some((recordKey, recordIndex) => { - if (pointKeys.has(recordKey)) { - if (startIndex === -1) { - startIndex = recordIndex; - } else { - endIndex = recordIndex; - return true; + return { + node: ( + { + const { shiftKey } = nativeEvent; + + let startIndex: number = -1; + let endIndex: number = -1; + + // Get range of this + if (shiftKey) { + const pointKeys = new Set([lastSelectedKey, key]); + + recordKeys.some((recordKey, recordIndex) => { + if (pointKeys.has(recordKey)) { + if (startIndex === -1) { + startIndex = recordIndex; + } else { + endIndex = recordIndex; + return true; + } } - } - - return false; - }); - } - if (endIndex !== -1 && startIndex !== endIndex) { - // Batch update selections - const rangeKeys = recordKeys.slice(startIndex, endIndex + 1); - const changedKeys: Key[] = []; - - if (hasKey) { - rangeKeys.forEach(recordKey => { - if (keySet.has(recordKey)) { - changedKeys.push(recordKey); - keySet.delete(recordKey); - } - }); - } else { - rangeKeys.forEach(recordKey => { - if (!keySet.has(recordKey)) { - changedKeys.push(recordKey); - keySet.add(recordKey); - } + return false; }); } - const keys = Array.from(keySet); - setSelectedKeys(keys); - if (onSelectMultiple) { - onSelectMultiple( - !hasKey, - keys.map(recordKey => getRecordByKey(recordKey)), - changedKeys.map(recordKey => getRecordByKey(recordKey)), - ); - } - } else { - // Single record selected - if (hasKey) { - keySet.delete(key); + if (endIndex !== -1 && startIndex !== endIndex) { + // Batch update selections + const rangeKeys = recordKeys.slice(startIndex, endIndex + 1); + const changedKeys: Key[] = []; + + if (checked) { + rangeKeys.forEach(recordKey => { + if (keySet.has(recordKey)) { + changedKeys.push(recordKey); + keySet.delete(recordKey); + } + }); + } else { + rangeKeys.forEach(recordKey => { + if (!keySet.has(recordKey)) { + changedKeys.push(recordKey); + keySet.add(recordKey); + } + }); + } + + const keys = Array.from(keySet); + setSelectedKeys(keys); + if (onSelectMultiple) { + onSelectMultiple( + !checked, + keys.map(recordKey => getRecordByKey(recordKey)), + changedKeys.map(recordKey => getRecordByKey(recordKey)), + ); + } } else { - keySet.add(key); - } + // Single record selected + if (checked) { + keySet.delete(key); + } else { + keySet.add(key); + } - triggerSingleSelection(key, !hasKey, Array.from(keySet), nativeEvent); - } + triggerSingleSelection(key, !checked, Array.from(keySet), nativeEvent); + } - setLastSelectedKey(key); - }} - /> - ); + setLastSelectedKey(key); + }} + /> + ), + checked, + }; }; } + const renderSelectionCell = (_: any, record: RecordType, index: number) => { + const { node, checked } = renderCell(_, record, index); + + if (customizeRenderCell) { + return customizeRenderCell(checked, record, index, node); + } + + return node; + }; + // Columns const selectionColumn = { width: selectionColWidth, className: `${prefixCls}-selection-column`, title: rowSelection.columnTitle || title, - render: renderCell, + render: renderSelectionCell, }; if (expandType === 'row' && columns.length) { diff --git a/components/table/index.en-US.md b/components/table/index.en-US.md index d7a045b789..b236ae150d 100644 --- a/components/table/index.en-US.md +++ b/components/table/index.en-US.md @@ -179,20 +179,21 @@ Properties for expandable. Properties for row selection. -| Property | Description | Type | Default | -| --- | --- | --- | --- | -| columnWidth | Set the width of the selection column | string\|number | `60px` | -| columnTitle | Set the title of the selection column | string\|React.ReactNode | - | -| fixed | Fixed selection column on the left | boolean | - | -| getCheckboxProps | Get Checkbox or Radio props | Function(record) | - | -| hideDefaultSelections | Remove the default `Select All` and `Select Invert` selections when [custom selection](#components-table-demo-row-selection-custom) | boolean | `false` | -| selectedRowKeys | Controlled selected row keys | string\[]\|number[] | \[] | -| selections | Custom selection [config](#rowSelection), only displays default selections when set to `true` | object\[]\|boolean | - | -| type | `checkbox` or `radio` | `checkbox` \| `radio` | `checkbox` | -| onChange | Callback executed when selected rows change | Function(selectedRowKeys, selectedRows) | - | -| onSelect | Callback executed when select/deselect one row | Function(record, selected, selectedRows, nativeEvent) | - | -| onSelectAll | Callback executed when select/deselect all rows | Function(selected, selectedRows, changeRows) | - | -| onSelectInvert | Callback executed when row selection is inverted | Function(selectedRows) | - | +| Property | Description | Type | Default | Version | +| --- | --- | --- | --- | --- | +| columnWidth | Set the width of the selection column | string\|number | `60px` | 4.0 | +| columnTitle | Set the title of the selection column | string\|React.ReactNode | - | 4.0 | +| fixed | Fixed selection column on the left | boolean | - | 4.0 | +| getCheckboxProps | Get Checkbox or Radio props | Function(record) | - | 4.0 | +| hideDefaultSelections | Remove the default `Select All` and `Select Invert` selections when [custom selection](#components-table-demo-row-selection-custom) | boolean | `false` | 4.0 | +| renderCell | Renderer of the table cell. Same as `render` in column | Function(checked, record, index, originNode) {} | - | 4.1 | +| selectedRowKeys | Controlled selected row keys | string\[]\|number[] | \[] | 4.0 | +| selections | Custom selection [config](#rowSelection), only displays default selections when set to `true` | object\[]\|boolean | - | 4.0 | +| type | `checkbox` or `radio` | `checkbox` \| `radio` | `checkbox` | 4.0 | +| onChange | Callback executed when selected rows change | Function(selectedRowKeys, selectedRows) | - | 4.0 | +| onSelect | Callback executed when select/deselect one row | Function(record, selected, selectedRows, nativeEvent) | - | 4.0 | +| onSelectAll | Callback executed when select/deselect all rows | Function(selected, selectedRows, changeRows) | - | 4.0 | +| onSelectInvert | Callback executed when row selection is inverted | Function(selectedRows) | - | 4.0 | ### scroll diff --git a/components/table/index.zh-CN.md b/components/table/index.zh-CN.md index ebc41ac55b..53f503a9ea 100644 --- a/components/table/index.zh-CN.md +++ b/components/table/index.zh-CN.md @@ -184,20 +184,21 @@ const columns = [ 选择功能的配置。 -| 参数 | 说明 | 类型 | 默认值 | -| --- | --- | --- | --- | -| columnWidth | 自定义列表选择框宽度 | string\|number | `60px` | -| columnTitle | 自定义列表选择框标题 | string\|React.ReactNode | - | -| fixed | 把选择框列固定在左边 | boolean | - | -| getCheckboxProps | 选择框的默认属性配置 | Function(record) | - | -| hideDefaultSelections | [自定义选择项](#components-table-demo-row-selection-custom)时去掉『全选』『反选』两个默认选项 | boolean | false | -| selectedRowKeys | 指定选中项的 key 数组,需要和 onChange 进行配合 | string\[]\|number[] | \[] | -| selections | 自定义选择项 [配置项](#selection), 设为 `true` 时使用默认选择项 | object\[]\|boolean | true | -| type | 多选/单选,`checkbox` or `radio` | string | `checkbox` | -| onChange | 选中项发生变化时的回调 | Function(selectedRowKeys, selectedRows) | - | -| onSelect | 用户手动选择/取消选择某行的回调 | Function(record, selected, selectedRows, nativeEvent) | - | -| onSelectAll | 用户手动选择/取消选择所有行的回调 | Function(selected, selectedRows, changeRows) | - | -| onSelectInvert | 用户手动选择反选的回调 | Function(selectedRows) | - | +| 参数 | 说明 | 类型 | 默认值 | 版本 | +| --- | --- | --- | --- | --- | +| columnWidth | 自定义列表选择框宽度 | string\|number | `60px` | 4.0 | +| columnTitle | 自定义列表选择框标题 | string\|React.ReactNode | - | 4.0 | +| fixed | 把选择框列固定在左边 | boolean | - | 4.0 | +| getCheckboxProps | 选择框的默认属性配置 | Function(record) | - | 4.0 | +| hideDefaultSelections | [自定义选择项](#components-table-demo-row-selection-custom)时去掉『全选』『反选』两个默认选项 | boolean | false | 4.0 | +| renderCell | 渲染勾选框,用法与 Column 的 `render` 相同 | Function(checked, record, index, originNode) {} | - | 4.1 | +| selectedRowKeys | 指定选中项的 key 数组,需要和 onChange 进行配合 | string\[]\|number[] | \[] | 4.0 | +| selections | 自定义选择项 [配置项](#selection), 设为 `true` 时使用默认选择项 | object\[]\|boolean | true | 4.0 | +| type | 多选/单选,`checkbox` or `radio` | string | `checkbox` | 4.0 | +| onChange | 选中项发生变化时的回调 | Function(selectedRowKeys, selectedRows) | - | 4.0 | +| onSelect | 用户手动选择/取消选择某行的回调 | Function(record, selected, selectedRows, nativeEvent) | - | 4.0 | +| onSelectAll | 用户手动选择/取消选择所有行的回调 | Function(selected, selectedRows, changeRows) | - | 4.0 | +| onSelectInvert | 用户手动选择反选的回调 | Function(selectedRows) | - | 4.0 | ### scroll diff --git a/components/table/interface.tsx b/components/table/interface.tsx index a9a0928c1a..33dde311f7 100644 --- a/components/table/interface.tsx +++ b/components/table/interface.tsx @@ -1,4 +1,9 @@ -import { GetRowKey, ColumnType as RcColumnType, ExpandableConfig } from 'rc-table/lib/interface'; +import { + GetRowKey, + ColumnType as RcColumnType, + RenderedCell as RcRenderedCell, + ExpandableConfig, +} from 'rc-table/lib/interface'; import { CheckboxProps } from '../checkbox'; import { PaginationConfig } from '../pagination'; @@ -129,6 +134,12 @@ export interface TableRowSelection { fixed?: boolean; columnWidth?: string | number; columnTitle?: string | React.ReactNode; + renderCell?: ( + value: boolean, + record: T, + index: number, + originNode: React.ReactNode, + ) => React.ReactNode | RcRenderedCell; } export type TransformColumns = (