mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-01 14:59:35 +08:00
bef9539e22
* feat: add ref * feat: table support reference * chore: rename * chore: proxy * test: add test case * chore: fix lint * docs: update desc * docs: update desc * docs: update desc * chore: clean up * chore: fix lint
227 lines
5.2 KiB
TypeScript
227 lines
5.2 KiB
TypeScript
import React from 'react';
|
|
import { Button, Segmented, Space, Switch, Table, Typography } from 'antd';
|
|
import type { TableProps } from 'antd';
|
|
|
|
interface RecordType {
|
|
id: number;
|
|
firstName: string;
|
|
lastName: string;
|
|
age: number;
|
|
address1: string;
|
|
address2: string;
|
|
address3: string;
|
|
}
|
|
|
|
const fixedColumns: TableProps<RecordType>['columns'] = [
|
|
{
|
|
title: 'ID',
|
|
dataIndex: 'id',
|
|
width: 100,
|
|
fixed: 'left',
|
|
},
|
|
{
|
|
title: 'FistName',
|
|
dataIndex: 'firstName',
|
|
width: 120,
|
|
fixed: 'left',
|
|
},
|
|
{
|
|
title: 'LastName',
|
|
dataIndex: 'lastName',
|
|
width: 120,
|
|
fixed: 'left',
|
|
},
|
|
{
|
|
title: 'Group',
|
|
width: 120,
|
|
render: (_, record) => `Group ${Math.floor(record.id / 4)}`,
|
|
onCell: (record) => ({
|
|
rowSpan: record.id % 4 === 0 ? 4 : 0,
|
|
}),
|
|
},
|
|
{
|
|
title: 'Age',
|
|
dataIndex: 'age',
|
|
width: 100,
|
|
onCell: (record) => ({
|
|
colSpan: record.id % 4 === 0 ? 2 : 1,
|
|
}),
|
|
},
|
|
{
|
|
title: 'Address 1',
|
|
dataIndex: 'address1',
|
|
onCell: (record) => ({
|
|
colSpan: record.id % 4 === 0 ? 0 : 1,
|
|
}),
|
|
},
|
|
{
|
|
title: 'Address 2',
|
|
dataIndex: 'address2',
|
|
},
|
|
{
|
|
title: 'Address 3',
|
|
dataIndex: 'address3',
|
|
},
|
|
{
|
|
title: 'Action',
|
|
width: 150,
|
|
fixed: 'right',
|
|
render: () => (
|
|
<Space>
|
|
<Typography.Link>Action1</Typography.Link>
|
|
<Typography.Link>Action2</Typography.Link>
|
|
</Space>
|
|
),
|
|
},
|
|
];
|
|
|
|
const columns: TableProps<RecordType>['columns'] = [
|
|
{
|
|
title: 'ID',
|
|
dataIndex: 'id',
|
|
width: 100,
|
|
},
|
|
{
|
|
title: 'FistName',
|
|
dataIndex: 'firstName',
|
|
width: 120,
|
|
},
|
|
{
|
|
title: 'LastName',
|
|
dataIndex: 'lastName',
|
|
width: 120,
|
|
},
|
|
];
|
|
|
|
const getData = (count: number) => {
|
|
const data: RecordType[] = new Array(count).fill(null).map((_, index) => ({
|
|
id: index,
|
|
firstName: `First_${index.toString(16)}`,
|
|
lastName: `Last_${index.toString(16)}`,
|
|
age: 25 + (index % 10),
|
|
address1: `New York No. ${index} Lake Park`,
|
|
address2: `London No. ${index} Lake Park`,
|
|
address3: `Sydney No. ${index} Lake Park`,
|
|
}));
|
|
|
|
return data;
|
|
};
|
|
|
|
const App = () => {
|
|
const [fixed, setFixed] = React.useState(true);
|
|
const [bordered, setBordered] = React.useState(true);
|
|
const [expanded, setExpanded] = React.useState(false);
|
|
const [empty, setEmpty] = React.useState(false);
|
|
const [count, setCount] = React.useState(10000);
|
|
|
|
const tblRef: Parameters<typeof Table>[0]['ref'] = React.useRef(null);
|
|
const data = React.useMemo(() => getData(count), [count]);
|
|
|
|
const mergedColumns = React.useMemo<typeof fixedColumns>(() => {
|
|
if (!fixed) {
|
|
return columns;
|
|
}
|
|
|
|
if (!expanded) {
|
|
return fixedColumns;
|
|
}
|
|
|
|
return fixedColumns.map((col) => ({ ...col, onCell: undefined }));
|
|
}, [expanded, fixed]);
|
|
|
|
const expandableProps = React.useMemo<TableProps<RecordType>['expandable']>(() => {
|
|
if (!expanded) {
|
|
return undefined;
|
|
}
|
|
|
|
return {
|
|
columnWidth: 48,
|
|
expandedRowRender: (record) => <p style={{ margin: 0 }}>🎉 Expanded {record.address1}</p>,
|
|
rowExpandable: (record) => record.id % 2 === 0,
|
|
};
|
|
}, [expanded]);
|
|
|
|
return (
|
|
<div style={{ padding: 64 }}>
|
|
<Space direction="vertical" style={{ width: '100%' }}>
|
|
<Space>
|
|
<Switch
|
|
checked={bordered}
|
|
onChange={() => setBordered(!bordered)}
|
|
checkedChildren="Bordered"
|
|
unCheckedChildren="Bordered"
|
|
/>
|
|
<Switch
|
|
checked={fixed}
|
|
onChange={() => setFixed(!fixed)}
|
|
checkedChildren="Fixed"
|
|
unCheckedChildren="Fixed"
|
|
/>
|
|
<Switch
|
|
checked={expanded}
|
|
onChange={() => setExpanded(!expanded)}
|
|
checkedChildren="Expandable"
|
|
unCheckedChildren="Expandable"
|
|
/>
|
|
<Switch
|
|
checked={empty}
|
|
onChange={() => setEmpty(!empty)}
|
|
checkedChildren="Empty"
|
|
unCheckedChildren="Empty"
|
|
/>
|
|
<Segmented
|
|
value={count}
|
|
onChange={(value: number) => setCount(value)}
|
|
options={[
|
|
{
|
|
label: 'None',
|
|
value: 0,
|
|
},
|
|
{
|
|
label: 'Less',
|
|
value: 4,
|
|
},
|
|
{
|
|
label: 'Lot',
|
|
value: 10000,
|
|
},
|
|
]}
|
|
/>
|
|
|
|
{data.length >= 999 && (
|
|
<Button
|
|
onClick={() => {
|
|
tblRef.current?.scrollTo({ index: 999 });
|
|
}}
|
|
>
|
|
Scroll To index 999
|
|
</Button>
|
|
)}
|
|
</Space>
|
|
|
|
<Table
|
|
bordered={bordered}
|
|
virtual
|
|
columns={mergedColumns}
|
|
scroll={{ x: 2000, y: 400 }}
|
|
rowKey="id"
|
|
dataSource={empty ? [] : data}
|
|
pagination={false}
|
|
ref={tblRef}
|
|
rowSelection={
|
|
expanded
|
|
? undefined
|
|
: {
|
|
type: 'radio',
|
|
columnWidth: 48,
|
|
}
|
|
}
|
|
expandable={expandableProps}
|
|
/>
|
|
</Space>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default App;
|