Skip to content

Commit

Permalink
feat: columnTitle render props (ant-design#41937)
Browse files Browse the repository at this point in the history
* feat: columnTitle render props

* feat: 添加测试

* docs: 修改table rowSelection interface

---------

Signed-off-by: afc163 <[email protected]>
Co-authored-by: afc163 <[email protected]>
  • Loading branch information
Zhou-Bill and afc163 authored Oct 24, 2023
1 parent d04e9ef commit a29a079
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 18 deletions.
27 changes: 27 additions & 0 deletions components/table/__tests__/Table.rowSelection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,33 @@ describe('Table.rowSelection', () => {
expect(container.querySelector('thead tr th')?.textContent).toBe('单选');
});

it('columnTitle for rowSelection to be renderProps', () => {
const { container } = render(
<Table
columns={columns}
dataSource={data}
rowSelection={{
columnTitle: (originalNode) =>
React.cloneElement(originalNode as any, {
'data-testid': 'selection-checkbox',
children: '多选',
}),
}}
/>,
);

expect(container.querySelector('thead tr th')?.textContent).toBe('多选');
expect(container.querySelector('thead tr th input')?.getAttribute('data-testid')).toBe(
'selection-checkbox',
);

fireEvent.click(container.querySelector('thead tr th input')!);
container.querySelectorAll('.ant-checkbox').forEach((checkbox) => {
expect(checkbox.querySelector('input')?.checked).toBe(true);
expect(checkbox.className.includes('ant-checkbox-indeterminate')).toBe(false);
});
});

// https://github.com/ant-design/ant-design/issues/11384
it('should keep item even if in filter', () => {
const filterColumns = [
Expand Down
45 changes: 30 additions & 15 deletions components/table/hooks/useSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ const useSelection = <RecordType extends AnyObject = AnyObject>(
// ===================== Render =====================
// Title Cell
let title: React.ReactNode;
let columnTitleCheckbox: React.ReactNode;
if (selectionType !== 'radio') {
let customizeSelections: React.ReactNode;
if (mergedSelections) {
Expand Down Expand Up @@ -456,22 +457,26 @@ const useSelection = <RecordType extends AnyObject = AnyObject>(
const allDisabledSomeChecked =
allDisabled && allDisabledData.some(({ checked }) => checked);

columnTitleCheckbox = (
<Checkbox
checked={
!allDisabled ? !!flattedData.length && checkedCurrentAll : allDisabledAndChecked
}
indeterminate={
!allDisabled
? !checkedCurrentAll && checkedCurrentSome
: !allDisabledAndChecked && allDisabledSomeChecked
}
onChange={onSelectAllChange}
disabled={flattedData.length === 0 || allDisabled}
aria-label={customizeSelections ? 'Custom selection' : 'Select all'}
skipGroup
/>
);

title = !hideSelectAll && (
<div className={`${prefixCls}-selection`}>
<Checkbox
checked={
!allDisabled ? !!flattedData.length && checkedCurrentAll : allDisabledAndChecked
}
indeterminate={
!allDisabled
? !checkedCurrentAll && checkedCurrentSome
: !allDisabledAndChecked && allDisabledSomeChecked
}
onChange={onSelectAllChange}
disabled={flattedData.length === 0 || allDisabled}
aria-label={customizeSelections ? 'Custom selection' : 'Select all'}
skipGroup
/>
{columnTitleCheckbox}
{customizeSelections}
</div>
);
Expand Down Expand Up @@ -699,14 +704,24 @@ const useSelection = <RecordType extends AnyObject = AnyObject>(
[`${prefixCls}-selection-col-with-dropdown`]: selections && selectionType === 'checkbox',
});

const renderColumnTitle = () => {
if (!rowSelection?.columnTitle) {
return title;
}
if (typeof rowSelection.columnTitle === 'function') {
return rowSelection.columnTitle(columnTitleCheckbox);
}
return rowSelection.columnTitle;
};

// Replace with real selection column
const selectionColumn: ColumnsType<RecordType>[0] & {
RC_TABLE_INTERNAL_COL_DEFINE: Record<string, any>;
} = {
fixed: mergedFixed,
width: selectionColWidth,
className: `${prefixCls}-selection-column`,
title: rowSelection.columnTitle || title,
title: renderColumnTitle(),
render: renderSelectionCell,
onCell: rowSelection.onCell,
[INTERNAL_COL_DEFINE]: { className: columnCls },
Expand Down
2 changes: 1 addition & 1 deletion components/table/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ Properties for row selection.
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| checkStrictly | Check table row precisely; parent row and children rows are not associated | boolean | true | 4.4.0 |
| columnTitle | Set the title of the selection column | ReactNode | - | |
| columnTitle | Set the title of the selection column | ReactNode \| (originalNode: ReactNode) => ReactNode | - | |
| columnWidth | Set the width of the selection column | string \| number | `32px` | |
| fixed | Fixed selection column on the left | boolean | - | |
| getCheckboxProps | Get Checkbox or Radio props | function(record) | - | |
Expand Down
2 changes: 1 addition & 1 deletion components/table/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ const columns = [
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| checkStrictly | checkable 状态下节点选择完全受控(父子数据选中状态不再关联) | boolean | true | 4.4.0 |
| columnTitle | 自定义列表选择框标题 | ReactNode | - | |
| columnTitle | 自定义列表选择框标题 | ReactNode \| (originalNode: ReactNode) => ReactNode | - | |
| columnWidth | 自定义列表选择框宽度 | string \| number | `32px` | |
| fixed | 把选择框列固定在左边 | boolean | - | |
| getCheckboxProps | 选择框的默认属性配置 | function(record) | - | |
Expand Down
2 changes: 1 addition & 1 deletion components/table/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export interface TableRowSelection<T> {
hideSelectAll?: boolean;
fixed?: FixedType;
columnWidth?: string | number;
columnTitle?: string | React.ReactNode;
columnTitle?: React.ReactNode | ((checkboxNode: React.ReactNode) => React.ReactNode);
checkStrictly?: boolean;
renderCell?: (
value: boolean,
Expand Down

0 comments on commit a29a079

Please sign in to comment.