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`] = `
+
+`;
+
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 = (