Skip to content

Commit 305549e

Browse files
authored
feat: improve element plus form component (#5072)
1 parent 958c8b4 commit 305549e

File tree

6 files changed

+213
-3
lines changed

6 files changed

+213
-3
lines changed

apps/web-ele/src/adapter/component/index.ts

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ import { $t } from '@vben/locales';
1515
import {
1616
ElButton,
1717
ElCheckbox,
18+
ElCheckboxButton,
1819
ElCheckboxGroup,
1920
ElDatePicker,
2021
ElDivider,
2122
ElInput,
2223
ElInputNumber,
2324
ElNotification,
25+
ElOption,
26+
ElRadio,
27+
ElRadioButton,
2428
ElRadioGroup,
2529
ElSelect,
2630
ElSelectV2,
@@ -79,7 +83,25 @@ async function initComponentAdapter() {
7983
);
8084
},
8185
Checkbox: ElCheckbox,
82-
CheckboxGroup: ElCheckboxGroup,
86+
CheckboxGroup: (props, { attrs, slots }) => {
87+
let defaultSlot;
88+
if (Reflect.has(slots, 'default')) {
89+
defaultSlot = slots.default;
90+
} else {
91+
const { options, isButton } = attrs;
92+
if (Array.isArray(options)) {
93+
defaultSlot = () =>
94+
options.map((option) =>
95+
h(isButton ? ElCheckboxButton : ElCheckbox, option),
96+
);
97+
}
98+
}
99+
return h(
100+
ElCheckboxGroup,
101+
{ ...props, ...attrs },
102+
{ ...slots, default: defaultSlot },
103+
);
104+
},
83105
// 自定义默认按钮
84106
DefaultButton: (props, { attrs, slots }) => {
85107
return h(ElButton, { ...props, attrs, type: 'info' }, slots);
@@ -104,8 +126,42 @@ async function initComponentAdapter() {
104126
},
105127
Input: withDefaultPlaceholder(ElInput, 'input'),
106128
InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
107-
RadioGroup: ElRadioGroup,
108-
Select: withDefaultPlaceholder(ElSelect, 'select'),
129+
RadioGroup: (props, { attrs, slots }) => {
130+
let defaultSlot;
131+
if (Reflect.has(slots, 'default')) {
132+
defaultSlot = slots.default;
133+
} else {
134+
const { options } = attrs;
135+
if (Array.isArray(options)) {
136+
defaultSlot = () =>
137+
options.map((option) =>
138+
h(attrs.isButton ? ElRadioButton : ElRadio, option),
139+
);
140+
}
141+
}
142+
return h(
143+
ElRadioGroup,
144+
{ ...props, ...attrs },
145+
{ ...slots, default: defaultSlot },
146+
);
147+
},
148+
Select: (props, { attrs, slots }) => {
149+
let defaultSlot;
150+
if (Reflect.has(slots, 'default')) {
151+
defaultSlot = slots.default;
152+
} else {
153+
const { options } = attrs;
154+
if (Array.isArray(options)) {
155+
defaultSlot = () => options.map((option) => h(ElOption, option));
156+
}
157+
}
158+
const placeholder = props?.placeholder || $t(`ui.placeholder.select`);
159+
return h(
160+
ElSelect,
161+
{ ...props, ...attrs, placeholder },
162+
{ ...slots, default: defaultSlot },
163+
);
164+
},
109165
Space: ElSpace,
110166
Switch: ElSwitch,
111167
TimePicker: (props, { attrs, slots }) => {

apps/web-ele/src/adapter/form.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ setupVbenForm<ComponentType>({
1212
config: {
1313
modelPropNameMap: {
1414
Upload: 'fileList',
15+
CheckboxGroup: 'model-value',
1516
},
1617
},
1718
defineRules: {

apps/web-ele/src/locales/langs/en-US/demos.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"title": "Demos",
33
"elementPlus": "Element Plus",
4+
"form": "Form",
45
"vben": {
56
"title": "Project",
67
"about": "About",

apps/web-ele/src/locales/langs/zh-CN/demos.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"title": "演示",
33
"elementPlus": "Element Plus",
4+
"form": "表单演示",
45
"vben": {
56
"title": "项目",
67
"about": "关于",

apps/web-ele/src/router/routes/modules/demos.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ const routes: RouteRecordRaw[] = [
2323
path: '/demos/element',
2424
component: () => import('#/views/demos/element/index.vue'),
2525
},
26+
{
27+
meta: {
28+
title: $t('demos.form'),
29+
},
30+
name: 'BasicForm',
31+
path: '/demos/form',
32+
component: () => import('#/views/demos/form/basic.vue'),
33+
},
2634
],
2735
},
2836
];
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<script lang="ts" setup>
2+
import { h } from 'vue';
3+
4+
import { Page } from '@vben/common-ui';
5+
6+
import { ElButton, ElCard, ElCheckbox, ElMessage } from 'element-plus';
7+
8+
import { useVbenForm } from '#/adapter/form';
9+
10+
const [Form, formApi] = useVbenForm({
11+
commonConfig: {
12+
// 所有表单项
13+
componentProps: {
14+
class: 'w-full',
15+
},
16+
},
17+
layout: 'horizontal',
18+
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
19+
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
20+
handleSubmit: (values) => {
21+
ElMessage.success(`表单数据:${JSON.stringify(values)}`);
22+
},
23+
schema: [
24+
{
25+
component: 'Input',
26+
fieldName: 'string',
27+
label: 'String',
28+
},
29+
{
30+
component: 'InputNumber',
31+
fieldName: 'number',
32+
label: 'Number',
33+
},
34+
{
35+
component: 'RadioGroup',
36+
fieldName: 'radio',
37+
label: 'Radio',
38+
componentProps: {
39+
options: [
40+
{ value: 'A', label: 'A' },
41+
{ value: 'B', label: 'B' },
42+
{ value: 'C', label: 'C' },
43+
{ value: 'D', label: 'D' },
44+
{ value: 'E', label: 'E' },
45+
],
46+
},
47+
},
48+
{
49+
component: 'RadioGroup',
50+
fieldName: 'radioButton',
51+
label: 'RadioButton',
52+
componentProps: {
53+
isButton: true,
54+
options: ['A', 'B', 'C', 'D', 'E', 'F'].map((v) => ({
55+
value: v,
56+
label: `选项${v}`,
57+
})),
58+
},
59+
},
60+
{
61+
component: 'CheckboxGroup',
62+
fieldName: 'checkbox',
63+
label: 'Checkbox',
64+
componentProps: {
65+
options: ['A', 'B', 'C'].map((v) => ({ value: v, label: `选项${v}` })),
66+
},
67+
},
68+
{
69+
component: 'CheckboxGroup',
70+
fieldName: 'checkbox1',
71+
label: 'Checkbox1',
72+
renderComponentContent: () => {
73+
return {
74+
default: () => {
75+
return ['A', 'B', 'C', 'D'].map((v) =>
76+
h(ElCheckbox, { label: v, value: v }),
77+
);
78+
},
79+
};
80+
},
81+
},
82+
{
83+
component: 'CheckboxGroup',
84+
fieldName: 'checkbotton',
85+
label: 'CheckBotton',
86+
componentProps: {
87+
isButton: true,
88+
options: [
89+
{ value: 'A', label: '选项A' },
90+
{ value: 'B', label: '选项B' },
91+
{ value: 'C', label: '选项C' },
92+
],
93+
},
94+
},
95+
{
96+
component: 'DatePicker',
97+
fieldName: 'date',
98+
label: 'Date',
99+
},
100+
{
101+
component: 'Select',
102+
fieldName: 'select',
103+
label: 'Select',
104+
componentProps: {
105+
options: [
106+
{ value: 'A', label: '选项A' },
107+
{ value: 'B', label: '选项B' },
108+
{ value: 'C', label: '选项C' },
109+
],
110+
},
111+
},
112+
],
113+
});
114+
function setFormValues() {
115+
formApi.setValues({
116+
string: 'string',
117+
number: 123,
118+
radio: 'B',
119+
radioButton: 'C',
120+
checkbox: ['A', 'C'],
121+
checkbotton: ['B', 'C'],
122+
checkbox1: ['A', 'B'],
123+
date: new Date(),
124+
select: 'B',
125+
});
126+
}
127+
</script>
128+
<template>
129+
<Page
130+
description="我们重新包装了CheckboxGroup、RadioGroup、Select,可以通过options属性传入选项属性数组以自动生成选项"
131+
title="表单演示"
132+
>
133+
<ElCard>
134+
<template #header>
135+
<div class="flex items-center">
136+
<span class="flex-auto">基础表单演示</span>
137+
<ElButton type="primary" @click="setFormValues">设置表单值</ElButton>
138+
</div>
139+
</template>
140+
<Form />
141+
</ElCard>
142+
</Page>
143+
</template>

0 commit comments

Comments
 (0)