Skip to content

Commit f0e1235

Browse files
authored
fix: auto spread width when table size is large than columns (#1021)
* chore: no need size * feat: support auto width * test: update test
1 parent 530fd48 commit f0e1235

File tree

6 files changed

+83
-19
lines changed

6 files changed

+83
-19
lines changed

docs/examples/virtual.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ interface RecordType {
1212
}
1313

1414
const columns: ColumnsType = [
15+
// { title: 'title1', dataIndex: 'a', key: 'a', width: 100,},
16+
// { title: 'title1', dataIndex: 'a', key: 'a', width: 100, },
1517
{ title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' },
1618
{ title: 'title2', dataIndex: 'b', key: 'b', width: 100, fixed: 'left', ellipsis: true },
1719
{
@@ -198,7 +200,7 @@ const Demo = () => {
198200
<VirtualTable
199201
columns={columns}
200202
// expandedRowRender={({ b, c }) => b || c}
201-
scroll={{ x: 1200, y: scrollY ? 200 : null }}
203+
scroll={{ x: 1300, y: scrollY ? 200 : null }}
202204
data={data}
203205
// data={[]}
204206
rowKey="indexKey"
@@ -209,6 +211,15 @@ const Demo = () => {
209211
}}
210212
// onRow={() => ({ className: 'rowed' })}
211213
rowClassName="nice-try"
214+
getContainerWidth={(ele, width) => {
215+
// Minus border
216+
const borderWidth = getComputedStyle(
217+
ele.querySelector('.rc-virtual-list'),
218+
).borderInlineStartWidth;
219+
const mergedWidth = width - parseInt(borderWidth, 10);
220+
221+
return mergedWidth;
222+
}}
212223
/>
213224
</div>
214225
);

src/Table.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ export interface TableProps<RecordType = unknown>
118118

119119
direction?: Direction;
120120

121+
sticky?: boolean | TableSticky;
122+
121123
// =================================== Internal ===================================
122124
/**
123125
* @private Internal usage, may remove by refactor. Should always use `columns` instead.
@@ -143,6 +145,14 @@ export interface TableProps<RecordType = unknown>
143145
// Force column to be average width if not set
144146
tailor?: boolean;
145147

148+
/**
149+
* @private Internal usage, may remove by refactor.
150+
*
151+
* !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!!
152+
*/
153+
// Pass the way to get real width. e.g. exclude the border width
154+
getContainerWidth?: (ele: HTMLElement, width: number) => number;
155+
146156
/**
147157
* @private Internal usage, may remove by refactor.
148158
*
@@ -151,8 +161,6 @@ export interface TableProps<RecordType = unknown>
151161
internalRefs?: {
152162
body: React.MutableRefObject<HTMLDivElement>;
153163
};
154-
155-
sticky?: boolean | TableSticky;
156164
}
157165

158166
function defaultEmpty() {
@@ -197,6 +205,7 @@ function Table<RecordType extends DefaultRecordType>(tableProps: TableProps<Reco
197205
transformColumns,
198206
internalRefs,
199207
tailor,
208+
getContainerWidth,
200209

201210
sticky,
202211
} = props;
@@ -281,6 +290,7 @@ function Table<RecordType extends DefaultRecordType>(tableProps: TableProps<Reco
281290
expandIconColumnIndex: expandableConfig.expandIconColumnIndex,
282291
direction,
283292
scrollWidth: useInternalHooks && tailor && typeof scrollX === 'number' ? scrollX : null,
293+
clientWidth: componentWidth,
284294
},
285295
useInternalHooks ? transformColumns : null,
286296
);
@@ -432,9 +442,14 @@ function Table<RecordType extends DefaultRecordType>(tableProps: TableProps<Reco
432442
};
433443

434444
const onFullTableResize = ({ width }) => {
435-
if (width !== componentWidth) {
445+
let mergedWidth = fullTableRef.current ? fullTableRef.current.offsetWidth : width;
446+
if (useInternalHooks && getContainerWidth) {
447+
mergedWidth = getContainerWidth(fullTableRef.current, mergedWidth) || mergedWidth;
448+
}
449+
450+
if (mergedWidth !== componentWidth) {
436451
triggerOnScroll();
437-
setComponentWidth(fullTableRef.current ? fullTableRef.current.offsetWidth : width);
452+
setComponentWidth(mergedWidth);
438453
}
439454
};
440455

src/VirtualTable/index.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,20 @@ const renderBody: CustomizeScrollBody<any> = (rawData, props) => {
1717

1818
export interface VirtualTableProps<RecordType> extends Omit<TableProps<RecordType>, 'scroll'> {
1919
scroll: {
20-
x: number;
20+
x?: number;
2121
y: number;
2222
};
2323
listItemHeight?: number;
2424
}
2525

26-
const PRESET_COLUMN_WIDTH = 100;
27-
2826
function VirtualTable<RecordType>(props: VirtualTableProps<RecordType>) {
2927
const { columns, scroll, prefixCls = DEFAULT_PREFIX, className, listItemHeight } = props;
3028

3129
let { x: scrollX, y: scrollY } = scroll || {};
3230

3331
// Fill scrollX
3432
if (typeof scrollX !== 'number') {
35-
scrollX = ((columns || []).length + 1) * PRESET_COLUMN_WIDTH;
36-
37-
if (process.env.NODE_ENV !== 'production') {
38-
warning(false, '`scroll.x` in virtual table must be number.');
39-
}
33+
scrollX = 1;
4034
}
4135

4236
// Fill scrollY

src/hooks/useColumns/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ function useColumns<RecordType>(
132132
columnWidth,
133133
fixed,
134134
scrollWidth,
135+
clientWidth,
135136
}: {
136137
prefixCls?: string;
137138
columns?: ColumnsType<RecordType>;
@@ -147,6 +148,7 @@ function useColumns<RecordType>(
147148
direction?: Direction;
148149
expandRowByClick?: boolean;
149150
columnWidth?: number | string;
151+
clientWidth: number;
150152
fixed?: FixedType;
151153
scrollWidth?: number;
152154
},
@@ -278,7 +280,11 @@ function useColumns<RecordType>(
278280
}
279281

280282
// ========================= FillWidth ========================
281-
const [filledColumns, realScrollWidth] = useWidthColumns(flattenColumns, scrollWidth);
283+
const [filledColumns, realScrollWidth] = useWidthColumns(
284+
flattenColumns,
285+
scrollWidth,
286+
clientWidth,
287+
);
282288

283289
return [mergedColumns, filledColumns, realScrollWidth];
284290
}

src/hooks/useColumns/useWidthColumns.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ function parseColWidth(totalWidth: number, width: string | number = '') {
1515
/**
1616
* Fill all column with width
1717
*/
18-
export default function useWidthColumns(flattenColumns: ColumnsType<any>, scrollWidth: number) {
18+
export default function useWidthColumns(
19+
flattenColumns: ColumnsType<any>,
20+
scrollWidth: number,
21+
clientWidth: number,
22+
) {
1923
return React.useMemo<[columns: ColumnsType<any>, realScrollWidth: number]>(() => {
2024
// Fill width if needed
2125
if (scrollWidth && scrollWidth > 0) {
@@ -34,7 +38,7 @@ export default function useWidthColumns(flattenColumns: ColumnsType<any>, scroll
3438
});
3539

3640
// Fill width
37-
let restWidth = scrollWidth - totalWidth;
41+
let restWidth = Math.max(scrollWidth - totalWidth, missWidthCount);
3842
let restCount = missWidthCount;
3943
const avgWidth = restWidth / missWidthCount;
4044

@@ -63,9 +67,25 @@ export default function useWidthColumns(flattenColumns: ColumnsType<any>, scroll
6367
return clone;
6468
});
6569

66-
return [filledColumns, realTotal];
70+
// If realTotal is less than clientWidth,
71+
// We need extend column width
72+
if (realTotal < clientWidth) {
73+
const scale = clientWidth / realTotal;
74+
75+
restWidth = clientWidth;
76+
77+
filledColumns.forEach((col: any, index) => {
78+
const colWidth = Math.floor(col.width * scale);
79+
80+
col.width = index === filledColumns.length - 1 ? restWidth : colWidth;
81+
82+
restWidth -= colWidth;
83+
});
84+
}
85+
86+
return [filledColumns, Math.max(realTotal, clientWidth)];
6787
}
6888

6989
return [flattenColumns, scrollWidth];
70-
}, [flattenColumns, scrollWidth]);
90+
}, [flattenColumns, scrollWidth, clientWidth]);
7191
}

tests/Virtual.spec.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ describe('Table.Virtual', () => {
106106
scroll: {} as any,
107107
});
108108

109-
expect(errSpy).toHaveBeenCalledWith('Warning: `scroll.x` in virtual table must be number.');
110109
expect(errSpy).toHaveBeenCalledWith('Warning: `scroll.y` in virtual table must be number.');
111110
});
112111

@@ -226,4 +225,23 @@ describe('Table.Virtual', () => {
226225

227226
expect(container.querySelector('.bamboo').textContent).toEqual('0');
228227
});
228+
229+
it('columns less than width', async () => {
230+
const { container } = getTable({
231+
columns: [{}, {}],
232+
scroll: {
233+
y: 10,
234+
},
235+
getContainerWidth: () => 200,
236+
data: [{}],
237+
});
238+
239+
resize(container.querySelector('.rc-table'));
240+
241+
await waitFakeTimer();
242+
243+
expect(container.querySelectorAll('col')).toHaveLength(2);
244+
expect(container.querySelectorAll('col')[0]).toHaveStyle({ width: '100px' });
245+
expect(container.querySelectorAll('col')[1]).toHaveStyle({ width: '100px' });
246+
});
229247
});

0 commit comments

Comments
 (0)