YbForm 表单
对 el-form (opens new window)的二次封装,将el-form-item
处理成数据结构方式 formItems
,不仅支持el-form
的所有功能,也会扩展一些功能,在使用上更加简捷。
# 基本使用
<template>
<div>
<yb-form
ref="form"
:formItems="formItems"
:model="formModel"
:rules="rules"
:label-width="labelWidth+'px'"
size="small"
@submit.native.prevent="onSubmit"
>
<template v-slot:name="formItem">
<el-input
v-model="formModel[formItem.prop]"
clearable
></el-input>
</template>
<template v-slot:region="formItem">
<el-select
v-model="formModel[formItem.prop]"
placeholder="请选择活动区域"
clearable
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</template>
<template v-slot:datetime="formItem">
<yb-range-wrapper separator="-">
<el-date-picker
slot="start"
type="date"
placeholder="选择日期"
v-model="formModel.date1"
style="width: 100%;"
></el-date-picker>
<el-time-picker
slot="end"
placeholder="选择时间"
v-model="formModel.date2"
style="width: 100%;"
></el-time-picker>
</yb-range-wrapper>
</template>
<template v-slot:delivery="formItem">
<el-switch v-model="formModel[formItem.prop]"></el-switch>
</template>
<template v-slot:resource="formItem">
<el-radio-group v-model="formModel[formItem.prop]">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</template>
<template v-slot:type="formItem">
<el-checkbox-group v-model="formModel[formItem.prop]">
<el-checkbox
label="美食/餐厅线上活动"
name="type"
></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</template>
<template v-slot:desc="formItem">
<el-input
type="textarea"
v-model="formModel[formItem.prop]"
></el-input>
</template>
<template v-slot:nums="formItem">
<el-slider
v-model="formModel[formItem.prop]"
show-input
:show-input-controls="false"
input-size="mini"
></el-slider>
</template>
<template v-slot:buttons="formItem">
<el-button type="primary" native-type="submit"
>立即创建</el-button
>
<el-button>取消</el-button>
</template>
</yb-form>
</div>
</template>
<script>
export default {
data() {
const formItems = [
{
label: '活动名称',
prop: 'name',
tooltip: ({ formItem, formModel }, h) =>
`活动名称字段是必填的,当前值:${
formModel.name ?? '-'
}`,
contentTip:
'是否是暗黑模式,默认会根据背景色 backgroundColor 的亮度自动设置。 如果是设置了容器的背景色而无法判断到,就可以使用该配置手动指定,echarts 会根据是否是暗黑模式调整文本等的颜色。',
rules: [
{
required: true,
message: '请输入活动名称',
trigger: 'blur',
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur',
},
],
},
{
label: '活动区域',
prop: 'region',
tooltip: '【区域一】对应的是广州市',
rules: [
{
required: true,
message: '请选择活动区域',
trigger: 'change',
},
],
contentTip: ({ formItem, formModel }, h) => {
return [
h(
'p',
{
style: {
marginTop: '3px',
marginBottom: 0,
},
},
'1.是否是暗黑模式,默认会根据背景色 backgroundColor 的亮度自动设置。'
),
h(
'p',
{
style: {
marginTop: '3px',
marginBottom: 0,
},
},
'2. 如果是设置了容器的背景色而无法判断到,就可以使用该配置手动指定,echarts 会根据是否是暗黑模式调整文本等的颜色。'
),
];
},
},
{
label: '活动时间',
prop: 'datetime',
},
{
label: '即时配送',
prop: 'delivery',
},
{
label: '活动性质',
prop: 'type',
defaultValue: [],
rules: [
{
type: 'array',
required: true,
message: '请至少选择一个活动性质',
trigger: 'change',
},
],
},
{
label: '特殊资源',
prop: 'resource',
rules: [
{
required: true,
message: '请选择活动资源',
trigger: 'change',
},
],
},
{
label: '活动形式',
prop: 'desc',
rules: [
{
required: true,
message: '请填写活动形式',
trigger: 'blur',
},
],
},
{
label: '滑动条',
prop: 'nums',
},
{
label: '',
prop: 'buttons',
},
];
const formModel = formItems
.concat([{ prop: 'date1' }, { prop: 'date2' }])
.reduce((tol, item) => {
return {
...tol,
[item.prop]:
typeof item.defaultValue !== 'undefined'
? item.defaultValue
: null,
};
}, {});
return {
labelWidth: 100,
formItems,
formModel,
rules: {
date1: [
{
type: 'date',
required: true,
message: '请选择日期',
trigger: 'change',
},
],
date2: [
{
type: 'date',
required: true,
message: '请选择时间',
trigger: 'change',
},
],
},
};
},
methods: {
onSubmit() {
this.$refs['form']
.getForm()
.validate()
.then(() => {
console.log('验证成功', this.formModel);
})
.catch((err, errFields) => {
console.log('验证失败', err, errFields);
});
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
显示 复制 复制
# 启用栅栏布局
inline
spans
<template>
<div>
<div style="margin-bottom:20px">
inline
<el-switch v-model="formProps['inline']"></el-switch>
spans
<el-switch v-model="formProps['spans']"></el-switch>
</div>
<yb-form
ref="form"
:inline="formProps['inline']"
:spans="formProps['spans']?{xl:8,lg:12}:false"
:formItems="formItems"
:model="formModel"
:rules="rules"
size="mini"
@submit.native.prevent="onSubmit"
>
<template v-slot:name="formItem">
<el-input
v-model="formModel[formItem.prop]"
clearable
></el-input>
</template>
<template v-slot:region="formItem">
<el-select
v-model="formModel[formItem.prop]"
placeholder="请选择活动区域"
clearable
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</template>
<template v-slot:datetime="formItem">
<yb-range-wrapper separator="-">
<el-date-picker
slot="start"
type="date"
placeholder="选择日期"
v-model="formModel.date1"
style="width: 100%;"
></el-date-picker>
<el-time-picker
slot="end"
placeholder="选择时间"
v-model="formModel.date2"
style="width: 100%;"
></el-time-picker>
</yb-range-wrapper>
</template>
<template v-slot:delivery="formItem">
<el-switch v-model="formModel[formItem.prop]"></el-switch>
</template>
<template v-slot:resource="formItem">
<el-radio-group
class="el-radio-button-group"
v-model="formModel[formItem.prop]"
>
<el-radio-button label="线上品牌商赞助"></el-radio-button>
<el-radio-button label="线下场地免费"></el-radio-button>
</el-radio-group>
</template>
<template v-slot:type="formItem">
<el-checkbox-group v-model="formModel[formItem.prop]">
<el-checkbox
label="美食/餐厅线上活动"
name="type"
></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</template>
<template v-slot:desc="formItem">
<el-input
type="textarea"
v-model="formModel[formItem.prop]"
></el-input>
</template>
<template v-slot:nums="formItem">
<el-slider
v-model="formModel[formItem.prop]"
show-input
:show-input-controls="false"
input-size="mini"
></el-slider>
</template>
<template v-slot:buttons="formItem">
<el-button type="primary" native-type="submit"
>立即创建</el-button
>
<el-button>取消</el-button>
</template>
</yb-form>
</div>
</template>
<script>
export default {
data() {
const formItems = [
{
label: '活动名称',
prop: 'name',
rules: [
{
required: true,
message: '请输入活动名称',
trigger: 'blur',
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur',
},
],
},
{
label: '活动区域',
prop: 'region',
rules: [
{
required: true,
message: '请选择活动区域',
trigger: 'change',
},
],
},
{
label: '活动时间',
prop: 'datetime',
},
{
label: '即时配送',
prop: 'delivery',
},
{
label: '活动性质',
prop: 'type',
defaultValue: [],
rules: [
{
type: 'array',
required: true,
message: '请至少选择一个活动性质',
trigger: 'change',
},
],
spans: { xl: 24, lg: 24, md: 24, sm: 24 },
},
{
label: '活动形式',
prop: 'desc',
rules: [
{
required: true,
message: '请填写活动形式',
trigger: 'blur',
},
],
spans: { xl: 24, lg: 24, md: 24, sm: 24 },
},
{
label: '特殊资源',
prop: 'resource',
rules: [
{
required: true,
message: '请选择活动资源',
trigger: 'change',
},
],
},
{
label: '滑动条',
prop: 'nums',
},
{
label: '',
prop: 'buttons',
excludeSpans: true,
},
];
const formModel = formItems
.concat([{ prop: 'date1' }, { prop: 'date2' }])
.reduce((tol, item) => {
return {
...tol,
[item.prop]:
typeof item.defaultValue !== 'undefined'
? item.defaultValue
: null,
};
}, {});
return {
formItems,
formModel,
rules: {
date1: [
{
type: 'date',
required: true,
message: '请选择日期',
trigger: 'change',
},
],
date2: [
{
type: 'date',
required: true,
message: '请选择时间',
trigger: 'change',
},
],
},
formProps: {
inline: true,
spans: true,
},
};
},
methods: {
onSubmit() {
this.$refs['form']
.getForm()
.validate()
.then(() => {
console.log('验证成功');
})
.catch((err, errFields) => {
console.log('验证失败', err, errFields);
});
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
显示 复制 复制
# 其他属性的演示
更多案例请查看 el-form (opens new window)
其他属性
label-width
label-position
label-suffix
size
disabled
inline
hide-required-asterisk
show-message
inline-message
status-icon
表单
<template>
<el-row>
<el-col :span="10">
<h2>其他属性</h2>
<div style="margin-bottom:20px">
label-width
<span
style="display:inline-block;width:200px;vertical-align: middle;"
><el-slider
v-model="formProps['label-width']"
:min="80"
:max="240"
></el-slider
></span>
</div>
<div style="margin-bottom:20px">
label-position
<el-radio-group
v-model="formProps['label-position']"
size="mini"
>
<el-radio-button label="left">left</el-radio-button>
<el-radio-button label="right">right</el-radio-button>
<el-radio-button label="top">top</el-radio-button>
</el-radio-group>
</div>
<div style="margin-bottom:20px">
label-suffix
<span
style="display:inline-block;width:200px;vertical-align: middle;"
>
<el-input
size="small"
v-model="formProps['label-suffix']"
></el-input
></span>
</div>
<div style="margin-bottom:20px">
size
<el-radio-group v-model="formProps['size']" size="mini">
<el-radio-button label="medium">medium</el-radio-button>
<el-radio-button label="small">small</el-radio-button>
<el-radio-button label="mini">mini</el-radio-button>
</el-radio-group>
</div>
<div style="margin-bottom:20px">
disabled
<el-switch v-model="formProps['disabled']"></el-switch>
</div>
<div style="margin-bottom:20px">
inline
<el-switch v-model="formProps['inline']"></el-switch>
</div>
<div style="margin-bottom:20px">
hide-required-asterisk
<el-switch
v-model="formProps['hide-required-asterisk']"
></el-switch>
</div>
<div style="margin-bottom:20px">
show-message
<el-switch v-model="formProps['show-message']"></el-switch>
</div>
<div style="margin-bottom:20px">
inline-message
<el-switch v-model="formProps['inline-message']"></el-switch>
</div>
<div style="margin-bottom:20px">
status-icon
<el-switch v-model="formProps['status-icon']"></el-switch>
</div>
</el-col>
<el-col :span="12">
<h2>表单</h2>
<yb-form
ref="form"
:formItems="formItems"
:model="formModel"
:rules="rules"
:label-width="formProps['label-width']+'px'"
:label-position="formProps['label-position']"
:size="formProps['size']"
:disabled="formProps['disabled']"
:inline="formProps['inline']"
:label-suffix="formProps['label-suffix']"
:status-icon="formProps['status-icon']"
:inline-message="formProps['inline-message']"
:show-message="formProps['show-message']"
:hide-required-asterisk="formProps['hide-required-asterisk']"
@submit.native.prevent="onSubmit"
>
<template v-slot:name="formItem">
<el-input
v-model="formModel[formItem.prop]"
clearable
></el-input>
</template>
<template v-slot:region="formItem">
<el-select
v-model="formModel[formItem.prop]"
placeholder="请选择活动区域"
clearable
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</template>
<template v-slot:datetime="formItem">
<yb-range-wrapper separator="-">
<el-date-picker
slot="start"
type="date"
placeholder="选择日期"
v-model="formModel.date1"
style="width: 100%;"
></el-date-picker>
<el-time-picker
slot="end"
placeholder="选择时间"
v-model="formModel.date2"
style="width: 100%;"
></el-time-picker>
</yb-range-wrapper>
</template>
<template v-slot:delivery="formItem">
<el-switch v-model="formModel[formItem.prop]"></el-switch>
</template>
<template v-slot:resource="formItem">
<el-radio-group v-model="formModel[formItem.prop]">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</template>
<template v-slot:type="formItem">
<el-checkbox-group v-model="formModel[formItem.prop]">
<el-checkbox
label="美食/餐厅线上活动"
name="type"
></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox
label="线下主题活动"
name="type"
></el-checkbox>
<el-checkbox
label="单纯品牌曝光"
name="type"
></el-checkbox>
</el-checkbox-group>
</template>
<template v-slot:desc="formItem">
<el-input
type="textarea"
v-model="formModel[formItem.prop]"
></el-input>
</template>
<template v-slot:buttons="formItem">
<el-button type="primary" native-type="submit"
>立即创建</el-button
>
<el-button>取消</el-button>
</template>
</yb-form>
</el-col>
</el-row>
</template>
<script>
export default {
data() {
const formItems = [
{
label: '活动名称',
prop: 'name',
rules: [
{
required: true,
message: '请输入活动名称',
trigger: 'blur',
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur',
},
],
},
{
label: '活动区域',
prop: 'region',
rules: [
{
required: true,
message: '请选择活动区域',
trigger: 'change',
},
],
},
{
label: '活动时间',
prop: 'datetime',
},
{
label: '即时配送',
prop: 'delivery',
},
{
label: '活动性质',
prop: 'type',
defaultValue: [],
rules: [
{
type: 'array',
required: true,
message: '请至少选择一个活动性质',
trigger: 'change',
},
],
},
{
label: '特殊资源',
prop: 'resource',
rules: [
{
required: true,
message: '请选择活动资源',
trigger: 'change',
},
],
},
{
label: '活动形式',
prop: 'desc',
rules: [
{
required: true,
message: '请填写活动形式',
trigger: 'blur',
},
],
},
{
label: '',
prop: 'buttons',
},
];
const formModel = formItems
.concat([{ prop: 'date1' }, { prop: 'date2' }])
.reduce((tol, item) => {
return {
...tol,
[item.prop]:
typeof item.defaultValue !== 'undefined'
? item.defaultValue
: null,
};
}, {});
return {
formItems,
formModel,
rules: {
date1: [
{
type: 'date',
required: true,
message: '请选择日期',
trigger: 'change',
},
],
date2: [
{
type: 'date',
required: true,
message: '请选择时间',
trigger: 'change',
},
],
},
formProps: {
'label-width': 120,
'label-position': 'left',
'label-suffix': '',
size: 'small',
disabled: false,
inline: false,
'hide-required-asterisk': false,
'show-message': true,
'inline-message': false,
'status-icon': false,
},
};
},
mounted() {
this.onSubmit();
},
methods: {
onSubmit() {
this.$refs['form']
.getForm()
.validate()
.then(() => {
console.log('验证成功');
})
.catch((err, errFields) => {
console.log('验证失败', err, errFields);
});
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
显示 复制 复制
# 控制字段显示/隐藏
- renderedController:根据每个字段设置是否渲染,默认渲染
字段设置为 false:相当于渲染节点时 return null,若设置 rules ,不进行校验
- showedController: 根据每个字段设置是否显示,默认显示
字段设置为 false:相当于节点添加样式 display: none,若设置 rules ,进行校验
<template>
<div style="margin-bottom:20px">
<el-button @click="toggleDescRender">
toggle 活动形式字段是否渲染
</el-button>
<el-button @click="toggleTypeShow">
toggle 活动性质字段是否隐藏
</el-button>
<el-button @click="toggleLoading"> 显示formitem的loading </el-button>
</div>
<yb-form
ref="form"
:formItems="formItems"
:model="formModel"
:rules="rules"
:label-width="labelWidth+'px'"
@submit.native.prevent="onSubmit"
:renderedController="renderedController"
:showedController="showedController"
:loadingController="loadingController"
>
<template v-slot:name="formItem">
<el-input v-model="formModel[formItem.prop]" clearable></el-input>
</template>
<template v-slot:region="formItem">
<el-select
v-model="formModel[formItem.prop]"
placeholder="请选择活动区域"
clearable
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</template>
<template v-slot:datetime="formItem">
<yb-range-wrapper separator="-">
<el-date-picker
slot="start"
type="date"
placeholder="选择日期"
v-model="formModel.date1"
style="width: 100%;"
></el-date-picker>
<el-time-picker
slot="end"
placeholder="选择时间"
v-model="formModel.date2"
style="width: 100%;"
></el-time-picker>
</yb-range-wrapper>
</template>
<template v-slot:delivery="formItem">
<el-switch v-model="formModel[formItem.prop]"></el-switch>
</template>
<template v-slot:resource="formItem">
<el-radio-group v-model="formModel[formItem.prop]">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</template>
<template v-slot:type="formItem">
<el-checkbox-group v-model="formModel[formItem.prop]">
<el-checkbox
label="美食/餐厅线上活动"
name="type"
></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</template>
<template v-slot:desc="formItem">
<el-input
type="textarea"
v-model="formModel[formItem.prop]"
></el-input>
</template>
<template v-slot:buttons="formItem">
<el-button type="primary" native-type="submit">立即创建</el-button>
<el-button>取消</el-button>
</template>
</yb-form>
</template>
<script>
export default {
data() {
const formItems = [
{
label: '活动名称',
prop: 'name',
rules: [
{
required: true,
message: '请输入活动名称',
trigger: 'blur',
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur',
},
],
},
{
label: '活动区域',
prop: 'region',
rules: [
{
required: true,
message: '请选择活动区域',
trigger: 'change',
},
],
},
{
label: '活动时间',
prop: 'datetime',
},
{
label: '即时配送',
prop: 'delivery',
},
{
label: '活动性质',
prop: 'type',
defaultValue: [],
rules: [
{
type: 'array',
required: true,
message: '请至少选择一个活动性质',
trigger: 'change',
},
],
},
{
label: '特殊资源',
prop: 'resource',
rules: [
{
required: true,
message: '请选择活动资源',
trigger: 'change',
},
],
},
{
label: '活动形式',
prop: 'desc',
rules: [
{
required: true,
message: '请填写活动形式',
trigger: 'blur',
},
],
},
{
label: '',
prop: 'buttons',
},
];
const showedController = {};
const renderedController = {};
const loadingController = {};
const formModel = formItems
.concat([{ prop: 'date1' }, { prop: 'date2' }])
.reduce((tol, item) => {
renderedController[item.prop] = true;
loadingController[item.prop] = false;
return {
...tol,
[item.prop]:
typeof item.defaultValue !== 'undefined'
? item.defaultValue
: null,
};
}, {});
return {
labelWidth: 100,
formItems,
formModel,
renderedController,
showedController,
loadingController,
rules: {
date1: [
{
type: 'date',
required: true,
message: '请选择日期',
trigger: 'change',
},
],
date2: [
{
type: 'date',
required: true,
message: '请选择时间',
trigger: 'change',
},
],
},
};
},
methods: {
onSubmit() {
this.$refs['form']
.getForm()
.validate()
.then(() => {
console.log('验证成功', this.formModel);
})
.catch((err, errFields) => {
console.log('验证失败', err, errFields);
});
},
toggleDescRender() {
this.renderedController['desc'] = !this.renderedController.desc;
},
toggleTypeShow() {
this.renderedController['type'] = !this.renderedController.type;
},
toggleLoading() {
this.loadingController['name'] = true;
setTimeout(() => {
this.loadingController['name'] = false;
}, 5 * 1000);
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
显示 复制 复制
# 折叠使用
- collapsed 不设置,不显示折叠 icon
- collapsed 设置 false,状态不折叠,显示折叠 icon
- collapsed 设置 true,状态折叠,显示折叠 icon
<template>
<div>
<yb-form
ref="form"
:formItems="formItems"
:model="formModel"
:spans="{xl:8,lg:12}"
label-width="100px"
label-position="top"
@submit.native.prevent="onSubmit"
>
<template v-slot:name="formItem">
<el-input
v-model="formModel[formItem.prop]"
clearable
></el-input>
</template>
<template v-slot:formRows="formItem">
<yb-rows-form
:formItems="rowsFormItems"
v-model="formModel[formItem.prop]"
:spans="true"
clearable
>
<template
v-slot:formItems="{rowFormItem,rowFormModel,rowKey}"
>
<el-input
v-model="rowFormModel[rowKey][rowFormItem.prop]"
clearable
></el-input>
</template>
</yb-rows-form>
</template>
<template v-slot:buttons="formItem">
<el-button type="primary" native-type="submit"
>立即创建</el-button
>
<el-button>取消</el-button>
</template>
</yb-form>
</div>
</template>
<script>
export default {
data() {
const formItems = [
{
label: '活动名称',
prop: 'name',
collapsed: false,
rules: [
{
required: true,
message: '请输入活动名称',
trigger: 'blur',
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur',
},
],
},
{
label: '活动信息',
prop: 'formRows',
spans: { xl: 24, lg: 24, md: 24, sm: 24, xs: 24 },
labelWidth: '0px',
collapsed: true,
// inFormItem: false,
rules: [
{
type: 'array',
required: true,
message: '请至少选择一个活动性质',
trigger: 'change',
},
],
},
{
label: '',
prop: 'buttons',
},
];
return {
formItems,
formModel: {
formRows: [{ delivery: '7777' }, {}],
name: null,
},
rowsFormItems: [
{
label: '活动区域',
prop: 'region',
tooltip: '活动区域必填',
rules: [
{
required: true,
message: '请选择活动区域',
trigger: 'change',
},
],
},
{
label: '活动时间',
prop: 'datetime',
tooltip: ({ formItem, formModel, rowKey }) => {
return `当前活动时间:${
formModel[rowKey].datetime ?? '-'
}`;
},
},
{
label: '即时配送',
prop: 'delivery',
},
{
label: '特殊资源',
prop: 'resource',
rules: [
{
required: true,
message: '请选择活动资源',
trigger: 'change',
},
],
},
],
};
},
methods: {
onSubmit() {
console.log(this.formModel);
this.$refs['form']
.getForm()
.validate()
.then(() => {
console.log('验证成功');
})
.catch((err) => {
console.log('验证失败', err);
});
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
显示 复制 复制
# 插槽的使用
- 所有 formItem 共用的插槽名称是: "formItems"
- 单独某个 formItem 的插槽名称: formItems[].prop
- 所有 formItem 共用的 label 插槽名称是: "formItemLabels"
- 单独某个 formItem 的 label 插槽名称是: formItems[].prop+"-label"
- 所有 formItem 共用的 error 插槽名称是: "formItemErrors"
- 单独某个 formItem 的 error 插槽名称是: formItems[].prop+"-error"
- 多个 formItem 共用的插槽时可以将多个插槽名称以","隔开来使用
<template>
<yb-form
ref="form"
:formItems="formItems"
:model="formModel"
:inline="true"
size="small"
@submit.native.prevent="onSubmit"
>
<!-- 所有formItem统一的插槽,插槽名称是"formItems",这里都默认插入input -->
<template v-slot:formItems="formItem">
<el-input v-model="formModel[formItem.prop]" clearable></el-input>
</template>
<!-- 单独某个formItem的插槽,插槽名称对应prop -->
<template v-slot:date="formItem">
{{consoleLog(formItem)}}
<el-date-picker
type="date"
placeholder="选择日期"
v-model="formModel[formItem.prop]"
style="width: 100%;"
></el-date-picker>
</template>
<template v-slot:buttons="formItem">
<el-button type="primary" native-type="submit">查询</el-button>
<el-button>重置</el-button>
</template>
<!-- 所有formItem的label插槽,插槽名称是"formItemLabels"-->
<template v-slot:formItemLabels="formItem">
<i class="el-icon-s-help"></i>{{formItem.label}}
</template>
<!-- 单独某个formItem的label插槽,插槽名称对应prop加上"-label"-->
<template v-slot:name-label="formItem">
<i class="el-icon-picture-outline-round"></i>{{formItem.label}}
</template>
<!-- 所有formItem的error插槽,插槽名称是"formItemErrors"-->
<template v-slot:formItemErrors="formItem">
<div><i class="el-icon-s-help"></i>{{formItem.error}}</div>
</template>
<!-- 单独某个formItem的error插槽,插槽名称对应prop加上"-error"-->
<template v-slot:name-error="formItem">
<div>
<i class="el-icon-picture-outline-round"></i>{{formItem.error}}
</div>
</template>
</yb-form>
</template>
<script>
export default {
data() {
const formItems = [
{
label: '名称',
prop: 'name',
rules: [
{
required: true,
message: '必填',
trigger: 'change',
},
],
},
{
label: '编码',
prop: 'code',
rules: [
{
required: true,
message: '必填',
trigger: 'change',
},
],
},
{
label: '日期',
prop: 'date',
rules: [
{
required: true,
message: '必填',
trigger: 'change',
},
],
},
{
label: '',
prop: 'buttons',
},
];
const formModel = formItems.reduce((tol, item) => {
return {
...tol,
[item.prop]:
typeof item.defaultValue !== 'undefined'
? item.defaultValue
: null,
};
}, {});
return {
formItems,
formModel,
};
},
methods: {
onSubmit() {
this.$refs['form']
.getForm()
.validate()
.then(() => {
console.log('验证成功');
})
.catch((err, errFields) => {
console.log('验证失败', err, errFields);
});
},
consoleLog(formItem) {
// console.log(formItem, '---formItem slot');
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
显示 复制 复制
# 分片渲染
开启 shardedRendering 属性,会进行异步分片逐步渲染每个表单项,如果渲染完马上要获取渲染完的 dom 等操作,提供了 shardedRenderEnd 事件,formItems 数组改变(只监听数组本身变化,通过 push 等方法改变数组是不会触发) 和 spans 改变 ,就会触发分片,最后触发 shardedRenderEnd 事件
1、非分片情况下,点击按钮打开弹窗一次性渲染大量表单项,明细卡顿的效果:
2、分片情况下,同样表单项的效果:
# Props
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
loadingController | 控制 formItem 区域的 loading 显示/隐藏 | object | - | {} |
renderedController | 控制是否渲染字段,优先级比 formItems[].unrendered 高 。 | object | - | {} |
showedController | 控制是否显示字段,不显示时相当于 display:none。 | object | - | {} |
formItems | 生成多个el-form-Item (opens new window)的数据,每一项的属性对应el-form-Item (opens new window)的属性,每个控件通过对应的 item.prop 的作用域插槽来添加。 | object[] | - | [] |
formItems[].prop | 注意:不允许是"formItems"、"formItemLabels"、"formItemErrors",不允许存在",",不允许以"-label"、"-error"结尾的字符串 | string | - | - |
formItems[].excludeSpans | 是否不包含在 spans | boolean | - | false |
formItems[].labelInTopForce | 开启 spans 后, 强制把标题显示在上面 | boolean | - | false |
是否不渲染 (不建议再使用,可以用 renderedController 代替) | boolean | - | false | |
formItems[].inFormItem | 是否渲染在 el-form-Item 组件内 | boolean | - | true |
formItems[].tooltip | 配置提示信息,在 label 文本后显示 | string | function({formItem,formModel},h) => string | - | - |
formItems[].contentTip | 在控件下面配置提示信息 | string | function({formItem,formModel},h) => string | - | - |
formItems[].collapsed | 是否折叠,详细使用YbForm 折叠使用 | boolean | - | - |
spans | 用栅栏布局对 formItems 排版,如果是 object 类型,将与默认的{ xl: 4,lg: 6,md: 8,sm: 12, xs: 24}进行合并,总占格数为 24 , 如果存在 { span:12 } 则 以 span 的值为准 | boolean | object | - | false |
gutter | 同 el-row 的 gutter | number | - | 10 |
rowType | 同 el-row 的 type,可选:"flex" | string | - | - |
rowJustify | 同 el-row 的 justify | string | - | 'start' |
rowAlign | 同 el-row 的 align | string | - | - |
shardedRendering | 是否分片渲染,表单项太多,一次性渲染会很明显的卡顿,开启后会进行异步一个表单项接着一个表单项的渲染 | boolean | - | false |
... | 其他属性同 el-form (opens new window) | - | - | - |
# Form Methods
方法调用方式应该是 this.$refs['form']['methodName']()
方法名称 | 说明 | 参数 | 返回值 |
---|---|---|---|
getForm | 取得 el-form 的组件实例 | - | - |
调用el-form Methods (opens new window)的方法,调用方式应该是 this.$refs['form'].getForm()['methodName']()
// 例如
this.$refs['form']
.getForm()
.validate()
.then(() => {});
1
2
3
4
5
2
3
4
5
# Form Events
事件名称 | 说明 | 参数 |
---|---|---|
shardedRenderEnd | 开启 shardedRendering 分片渲染后,最后渲染完成会触发的事件 | - |
其他事件是同 el-form Events (opens new window)一致的
上次更新: 2024/11/26, 19:21:17