Skip to content

Commit 1272457

Browse files
committed
feat: add resize table column
1 parent 17a1ca5 commit 1272457

File tree

10 files changed

+400
-11
lines changed

10 files changed

+400
-11
lines changed

components/table/Table.tsx

+11-4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
4343
import classNames from '../_util/classNames';
4444
import omit from '../_util/omit';
4545
import { initDefaultProps } from '../_util/props-util';
46-
import { useProvideSlots } from './context';
46+
import { useProvideSlots, useProvideTableContext } from './context';
4747
import type { ContextSlots } from './context';
4848
import useColumns from './hooks/useColumns';
4949
import { convertChildrenToColumns } from './util';
@@ -195,7 +195,10 @@ export const tableProps = () => {
195195
>,
196196
default: undefined,
197197
},
198-
198+
onResizeColumn: {
199+
type: Function as PropType<(w: number, col: ColumnsType) => void>,
200+
default: undefined,
201+
},
199202
rowSelection: { type: Object as PropType<TableRowSelection>, default: undefined },
200203
getPopupContainer: { type: Function as PropType<GetPopupContainer>, default: undefined },
201204
scroll: {
@@ -243,15 +246,19 @@ const InteralTable = defineComponent<
243246
'customFilterIcon',
244247
'customFilterDropdown',
245248
],
246-
setup(props, { attrs, slots, expose }) {
249+
setup(props, { attrs, slots, expose, emit }) {
247250
devWarning(
248251
!(typeof props.rowKey === 'function' && props.rowKey.length > 1),
249252
'Table',
250253
'`index` parameter of `rowKey` function is deprecated. There is no guarantee that it will work as expected.',
251254
);
252255

253256
useProvideSlots(computed(() => props.contextSlots));
254-
257+
useProvideTableContext({
258+
onResizeColumn: (w, col) => {
259+
emit('resizeColumn', w, col);
260+
},
261+
});
255262
const screens = useBreakpoint();
256263

257264
const mergedColumns = computed(() => {

components/table/context.ts

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ComputedRef, InjectionKey } from 'vue';
22
import { computed, inject, provide } from 'vue';
3+
import type { ColumnType } from './interface';
34

45
export type ContextSlots = {
56
emptyText?: (...args: any[]) => any;
@@ -15,14 +16,28 @@ export type ContextSlots = {
1516
[key: string]: ((...args: any[]) => any) | undefined;
1617
};
1718

18-
export type ContextProps = ComputedRef<ContextSlots>;
19+
type SlotsContextProps = ComputedRef<ContextSlots>;
1920

20-
export const ContextKey: InjectionKey<ContextProps> = Symbol('ContextProps');
21+
const SlotsContextKey: InjectionKey<SlotsContextProps> = Symbol('SlotsContextProps');
2122

22-
export const useProvideSlots = (props: ContextProps) => {
23-
provide(ContextKey, props);
23+
export const useProvideSlots = (props: SlotsContextProps) => {
24+
provide(SlotsContextKey, props);
2425
};
2526

2627
export const useInjectSlots = () => {
27-
return inject(ContextKey, computed(() => ({})) as ContextProps);
28+
return inject(SlotsContextKey, computed(() => ({})) as SlotsContextProps);
29+
};
30+
31+
type ContextProps = {
32+
onResizeColumn: (w: number, column: ColumnType<any>) => void;
33+
};
34+
35+
const ContextKey: InjectionKey<ContextProps> = Symbol('ContextProps');
36+
37+
export const useProvideTableContext = (props: ContextProps) => {
38+
provide(ContextKey, props);
39+
};
40+
41+
export const useInjectTableContext = () => {
42+
return inject(ContextKey, { onResizeColumn: () => {} } as ContextProps);
2843
};

components/table/demo/index.vue

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<RowSelectionCustom />
2323
<RowSelection />
2424
<Sticky />
25+
<ResizableColumn />
2526
<Size />
2627
<Stripe />
2728
<Summary />
@@ -57,6 +58,7 @@ import Stripe from './stripe.vue';
5758
import MultipleSorter from './multiple-sorter.vue';
5859
import Summary from './summary.vue';
5960
import Sticky from './sticky.vue';
61+
import ResizableColumn from './resizable-column.vue';
6062
import CN from '../index.zh-CN.md';
6163
import US from '../index.en-US.md';
6264
import { defineComponent } from '@vue/runtime-core';
@@ -91,6 +93,7 @@ export default defineComponent({
9193
MultipleSorter,
9294
Summary,
9395
Sticky,
96+
ResizableColumn,
9497
},
9598
});
9699
</script>
+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<docs>
2+
---
3+
order: 0
4+
title:
5+
en-US: Resizable column
6+
zh-CN: 可伸缩列
7+
---
8+
9+
## zh-CN
10+
11+
设置 resizable 开启拖动列
12+
13+
鼠标 hover 到 Name、 Age 分割线上体验一下吧
14+
15+
## en-US
16+
17+
set resizable for drag column
18+
</docs>
19+
20+
<template>
21+
<a-table :columns="columns" :data-source="data" @resizeColumn="handleResizeColumn">
22+
<template #headerCell="{ column }">
23+
<template v-if="column.key === 'name'">
24+
<span>
25+
<smile-outlined />
26+
Name
27+
</span>
28+
</template>
29+
</template>
30+
31+
<template #bodyCell="{ column, record }">
32+
<template v-if="column.key === 'name'">
33+
<a>
34+
{{ record.name }}
35+
</a>
36+
</template>
37+
<template v-else-if="column.key === 'tags'">
38+
<span>
39+
<a-tag
40+
v-for="tag in record.tags"
41+
:key="tag"
42+
:color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
43+
>
44+
{{ tag.toUpperCase() }}
45+
</a-tag>
46+
</span>
47+
</template>
48+
<template v-else-if="column.key === 'action'">
49+
<span>
50+
<a>Invite 一 {{ record.name }}</a>
51+
<a-divider type="vertical" />
52+
<a>Delete</a>
53+
<a-divider type="vertical" />
54+
<a class="ant-dropdown-link">
55+
More actions
56+
<down-outlined />
57+
</a>
58+
</span>
59+
</template>
60+
</template>
61+
</a-table>
62+
</template>
63+
<script lang="ts">
64+
import { SmileOutlined, DownOutlined } from '@ant-design/icons-vue';
65+
import { defineComponent, ref } from 'vue';
66+
67+
const data = [
68+
{
69+
key: '1',
70+
name: 'John Brown',
71+
age: 32,
72+
address: 'New York No. 1 Lake Park',
73+
tags: ['nice', 'developer'],
74+
},
75+
{
76+
key: '2',
77+
name: 'Jim Green',
78+
age: 42,
79+
address: 'London No. 1 Lake Park',
80+
tags: ['loser'],
81+
},
82+
{
83+
key: '3',
84+
name: 'Joe Black',
85+
age: 32,
86+
address: 'Sidney No. 1 Lake Park',
87+
tags: ['cool', 'teacher'],
88+
},
89+
];
90+
91+
export default defineComponent({
92+
components: {
93+
SmileOutlined,
94+
DownOutlined,
95+
},
96+
setup() {
97+
const columns = ref([
98+
{
99+
name: 'Name',
100+
dataIndex: 'name',
101+
key: 'name',
102+
resizable: true,
103+
width: 150,
104+
},
105+
{
106+
title: 'Age',
107+
dataIndex: 'age',
108+
key: 'age',
109+
resizable: true,
110+
width: 100,
111+
minWidth: 100,
112+
maxWidth: 200,
113+
},
114+
{
115+
title: 'Address',
116+
dataIndex: 'address',
117+
key: 'address',
118+
},
119+
{
120+
title: 'Tags',
121+
key: 'tags',
122+
dataIndex: 'tags',
123+
},
124+
{
125+
title: 'Action',
126+
key: 'action',
127+
},
128+
]);
129+
return {
130+
data,
131+
columns,
132+
handleResizeColumn: (w, col) => {
133+
col.width = w;
134+
},
135+
};
136+
},
137+
});
138+
</script>

components/table/style/index.less

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
@import '../../style/mixins/index';
33
@import './size';
44
@import './bordered';
5+
@import './resize.less';
56

67
@table-prefix-cls: ~'@{ant-prefix}-table';
78
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';

components/table/style/resize.less

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.@{table-prefix-cls}-resize-handle {
2+
position: absolute;
3+
top: 0;
4+
height: 100% !important;
5+
bottom: 0;
6+
left: auto !important;
7+
right: -8px;
8+
cursor: col-resize;
9+
touch-action: none;
10+
user-select: auto;
11+
width: 16px;
12+
z-index: 1;
13+
&-line {
14+
display: block;
15+
width: 3px;
16+
margin-left: 7px;
17+
height: 100% !important;
18+
background-color: @primary-color;
19+
opacity: 0;
20+
}
21+
&:hover &-line {
22+
opacity: 1;
23+
}
24+
}
25+
26+
.dragging .@{table-prefix-cls}-resize-handle-line {
27+
opacity: 1;
28+
}

components/vc-table/Cell/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ export default defineComponent<CellProps>({
273273
<Component {...componentProps}>
274274
{appendNode}
275275
{childNode}
276+
{slots.dragHandle?.()}
276277
</Component>
277278
);
278279
};

0 commit comments

Comments
 (0)