Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix the style of the parent header in the fixed part sub-level c… #1028

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
32 changes: 25 additions & 7 deletions docs/examples/fixedColumns-resize.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useCallback } from 'react';
import type { ColumnGroupType, ColumnType } from '@/interface';
import Table from 'rc-table';
import React, { useCallback, useState } from 'react';
import '../../assets/index.less';
import type { ColumnType } from '@/interface';

interface RecordType {
a: string;
Expand All @@ -11,9 +11,15 @@ interface RecordType {
key: string;
}

const defaultColumns: ColumnType<RecordType>[] = [
{ title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' },
{ title: 'title2', dataIndex: 'b', key: 'b', width: 100, fixed: 'left', ellipsis: true },
const defaultColumns: (ColumnType<RecordType> | ColumnGroupType<RecordType>)[] = [
{
title: 'firstGroup',
fixed: 'left',
children: [
{ title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' },
{ title: 'title2', dataIndex: 'b', key: 'b', width: 100, ellipsis: true },
],
},
{ title: 'title3', dataIndex: 'c', key: 'c' },
{ title: 'title4', dataIndex: 'b', key: 'd' },
{ title: 'title5', dataIndex: 'b', key: 'e' },
Expand All @@ -28,8 +34,13 @@ const defaultColumns: ColumnType<RecordType>[] = [
{ title: 'title16', dataIndex: 'b', key: 'j5' },
{ title: 'title17', dataIndex: 'b', key: 'j6' },
{ title: 'title18', dataIndex: 'b', key: 'j7' },
{ title: 'title19', dataIndex: 'b', key: 'k', width: 50, fixed: 'right' },
{ title: 'title20', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' },
{
title: 'lastGroup',
children: [
{ title: 'title19', dataIndex: 'b', key: 'k', width: 50 },
{ title: 'title20', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' },
],
},
];

const data: RecordType[] = Array.from(new Array(200).fill(1), (v, index) => {
Expand All @@ -45,6 +56,7 @@ const Demo = () => {
const [isShown, setIsShown] = useState(false);
const [renderTime, setRenderTime] = useState(0);
const [isFixed, setIsFixed] = useState(true);
const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr');
const [columns, setColumns] = useState(defaultColumns);
const onToggleSideBar = useCallback(() => {
const s = window.performance.now();
Expand Down Expand Up @@ -82,6 +94,10 @@ const Demo = () => {
});
}, []);

const onLayoutChange = useCallback(() => {
setDirection(preState => (preState === 'ltr' ? 'rtl' : 'ltr'));
}, []);

const expandedRowRender = useCallback(({ b, c }) => b || c, []);

return (
Expand All @@ -91,6 +107,7 @@ const Demo = () => {
<button onClick={onToggleFixed}>切换固定列</button>
<button onClick={onRemoveColumn}>删除列</button>
<button onClick={onAddColumn}>增加列</button>
<button onClick={onLayoutChange}>切换布局方向</button>
<p>更新用时:{renderTime} ms</p>
</div>
<div
Expand All @@ -107,6 +124,7 @@ const Demo = () => {
<div style={{ flex: `0 0 ${isShown ? '10px' : '80px'}` }} />
<div style={{ flex: 1, overflow: 'hidden' }}>
<Table
direction={direction}
columns={columns}
scroll={isFixed ? { x: 1200 } : null}
data={data}
Expand Down
31 changes: 26 additions & 5 deletions src/utils/fixUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ export interface FixedInfo {
isSticky: boolean;
}

function hasColumnChildren<RecordType>(
column: ColumnType<RecordType> | ColumnGroupType<RecordType>,
): boolean {
// no children only
if (!(column as ColumnGroupType<RecordType>)?.children) {
return true;
}
if (
(column as ColumnGroupType<RecordType>)?.children &&
(column as ColumnGroupType<RecordType>)?.children.length > 0
) {
return (column as ColumnGroupType<RecordType>)?.children.some(children =>
hasColumnChildren(children),
);
}
}

export function getCellFixedInfo<RecordType = any>(
colStart: number,
colEnd: number,
Expand All @@ -33,9 +50,10 @@ export function getCellFixedInfo<RecordType = any>(
let fixLeft: number;
let fixRight: number;

if (startColumn.fixed === 'left') {
// RTL layout calculation logic processing
if (startColumn.fixed === 'left' || endColumn.fixed === 'left') {
fixLeft = stickyOffsets.left[direction === 'rtl' ? colEnd : colStart];
} else if (endColumn.fixed === 'right') {
} else if (endColumn.fixed === 'right' || startColumn.fixed === 'right') {
fixRight = stickyOffsets.right[direction === 'rtl' ? colStart : colEnd];
}

Expand All @@ -48,23 +66,26 @@ export function getCellFixedInfo<RecordType = any>(
const nextColumn = columns[colEnd + 1];
const prevColumn = columns[colStart - 1];

// iff all children of a cell have exactly one child, then onlyChildren is true
const hasChildren = hasColumnChildren(curColumns);

// no children only
const canLastFix = !(curColumns as ColumnGroupType<RecordType>)?.children;

if (direction === 'rtl') {
if (fixLeft !== undefined) {
const prevFixLeft = prevColumn && prevColumn.fixed === 'left';
firstFixLeft = !prevFixLeft && canLastFix;
firstFixLeft = !prevFixLeft && (canLastFix || hasChildren);
} else if (fixRight !== undefined) {
const nextFixRight = nextColumn && nextColumn.fixed === 'right';
lastFixRight = !nextFixRight && canLastFix;
lastFixRight = !nextFixRight && (canLastFix || hasChildren);
}
} else if (fixLeft !== undefined) {
const nextFixLeft = nextColumn && nextColumn.fixed === 'left';
lastFixLeft = !nextFixLeft && canLastFix;
} else if (fixRight !== undefined) {
const prevFixRight = prevColumn && prevColumn.fixed === 'right';
firstFixRight = !prevFixRight && canLastFix;
firstFixRight = !prevFixRight && (canLastFix || hasChildren);
}

return {
Expand Down
38 changes: 38 additions & 0 deletions tests/FixedColumn.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,42 @@ describe('Table.FixedColumn', () => {
await safeAct(wrapper);
expect(wrapper.find('.rc-table-cell-fix-left-all')).toHaveLength(10);
});

describe('freeze column effect under multi-level header', () => {
let wrapper;

// freeze column data for columns
const customColumns = [
...columns.slice(0, columns.length - 2),
{
title: 'title12',
children: [
{ title: 'title13', dataIndex: 'b', key: 'k' },
{ title: 'title14', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' },
],
},
];

beforeEach(() => {
act(() => {
wrapper = mount(<Table columns={customColumns} data={data} />);
});
});

afterEach(() => {
wrapper.unmount();
});

it('table header only has two frozen column cells', async () => {
expect(wrapper.find('.rc-table-thead .rc-table-cell-fix-right-first')).toHaveLength(2);
});

it('freeze column cells at the end of the corresponding row', async () => {
const tr = wrapper.find('.rc-table-thead tr');

tr.forEach(trElement => {
expect(trElement.find('th').last().hasClass('rc-table-cell-fix-right-first')).toBeTruthy();
});
});
});
});
Loading