Vue+Element动态表单校验
最近项目中需要动态创建若干表单,并附加检验规则,踩了很多坑,在此写了一个小demo做一个记录
1. 效果展示
Vue+Element动态表单校验
2. 动态表单的创建(核心代码)
<div v-for='(item, index) in dynamicFormData' :key='index'>
<el-form :model='item' ref='dynamicForm' >
<el-form-item prop = "channelName">
<el-input v-model = "item.channelName" />
</el-form-item>
</el-form>
</div>
3. 多个表单同时校验(核心代码)
let flag = 0
for (let i = 0; i < this.passageway.count; i++) {
try {
let k = await this.$refs['dynamicForm'][i].validate()
flag++
} catch (e) {
console.log('表单校验失败')
}
}
// 根据flag === count来判断是否校验成功
4.完整代码
<template>
<div>
<h1>动态表单校验</h1>
<el-row>
<el-col :span='12'>
<span>请选择通道数目</span>
<el-select
v-model='passageway.count'
clearable
placeholder='请选择通道数目'
@change='changeCount'
style='width: 220px; margin-left: 20px'
>
<el-option
v-for='item in countArr'
:label='item.label'
:key='item.value'
:value='item.value'
/>
</el-select>
</el-col>
</el-row>
<div v-for='(item, index) in dynamicFormData' :key='index'>
<el-form
:model='item'
label-position='right'
label-width='100px'
ref='dynamicForm'
size='small'
:inline='true'
label-suffix=':'
>
<div class='p-title'>通道{{ index + 1 }}</div>
<!-- 第一行 -->
<el-row>
<el-col :span='8'>
<el-form-item
label='通道名称'
prop='channelName'
:rules="[
{
required: true,
message: '通道名称不能为空',
trigger: ['blur', 'change'],
},
]"
>
<el-input
type='text'
v-model='item.channelName'
style='width: 220px'
clearable
maxlength='50'
placeholder='请输入通道名称'
/>
</el-form-item>
</el-col>
<el-col :span='8'>
<el-form-item label='设备类型' prop='terminalType' :rules="[
{
required: true,
message: '设备类型不能为空',
trigger: ['blur','change'],
},
]">
<el-select v-model='item.terminalType' placeholder='请选择设备类型' style='width: 220px' clearable>
<el-option
v-for='item in deviceType'
:key='item.value'
:label='item.label'
:value='item.value'>
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span='8'>
<el-form-item label='摄像机种类' prop='vidiconSpecies'>
<el-input
type='text'
v-model='item.vidiconSpecies'
clearable
maxlength='50'
style='width: 220px'
placeholder='请输入摄像机种类'
/>
</el-form-item>
</el-col>
</el-row>
<!-- 第二行 -->
<el-row>
<el-col :span='8'>
<el-form-item label='型号' prop='model'>
<el-input
type='text'
v-model='item.model'
style='width: 220px'
clearable
maxlength='50'
placeholder='请输入型号'
/>
</el-form-item>
</el-col>
<el-col :span='8'>
<el-form-item label='生产厂家' prop='productionFactory'>
<el-input
type='text'
v-model='item.productionFactory'
style='width: 220px'
clearable
maxlength='50'
placeholder='请输入生产厂家'
/>
</el-form-item>
</el-col>
<el-col :span='8'>
<el-form-item label='安装地点' prop='installAddress'>
<el-input
type='text'
v-model='item.installAddress'
style='width: 220px'
clearable
maxlength='50'
placeholder='请输入安装地点'
/>
</el-form-item>
</el-col>
</el-row>
<!-- 第三行 -->
<el-row>
<el-col :span='8'>
<el-form-item label='使用状态' prop='usedState'>
<el-radio v-model='item.usedState' label='1'>启用</el-radio>
<el-radio v-model='item.usedState' label='0'>停用</el-radio>
</el-form-item>
</el-col>
<el-col :span='8'>
<el-form-item label='云台功能' prop='cloudPlatformFunction'>
<el-radio v-model='item.cloudPlatformFunction' label='1'
>启用
</el-radio
>
<el-radio v-model='item.cloudPlatformFunction' label='0'
>停用
</el-radio
>
</el-form-item>
</el-col>
<el-col :span='8'>
<el-form-item label='物理通道' prop='physicalChannel'>
<el-input
type='text'
v-model='item.physicalChannel'
style='width: 220px'
clearable
maxlength='50'
placeholder='请输入终端型号'
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<el-button type='primary' @click='submitForm' v-if='passageway.count'>提交</el-button>
</div>
</template>
<script>
export default {
data() {
return {
passageway: {
count: 1 // 默认通道数量
},
countArr: [], // 通道数量下拉框
dynamicFormData: [],// 表单数组
deviceType: [ // 设备类型
{ label: '车载视频设备', value: 1 },
{ label: '电动采集器', value: 2 },
{ label: '数据中心一体机', value: 3 }
]
}
},
created() {
this.initCount()
this.initCountData()
},
methods: {
// 通道数目变化
changeCount(e) {
this.passageway.count = e
this.initCountData()
},
// 通道数目0-12
initCount() {
for (let i = 0; i <= 12; i++) {
this.countArr.push({
label: i,
value: i
})
}
},
// 初始化通道表单数组
initCountData() {
this.dynamicFormData = []
for (let i = 0; i < this.passageway.count; i++) {
this.dynamicFormData.push({
channelName: 'CH' + (i + 1),
terminalType: undefined,
vidiconSpecies: undefined,
model: undefined,
productionFactory: undefined,
installAddress: undefined,
usedState: '1',
cloudPlatformFunction: '1',
physicalChannel: undefined
})
}
},
// 校验表单
async submitForm() {
// 多个表单进行校验的标识
let flag = 0
for (let i = 0; i < this.passageway.count; i++) {
try {
let k = await this.$refs['dynamicForm'][i].validate()
flag++
} catch (e) {
console.log('表单校验失败')
}
}
if (flag !== this.passageway.count) {
this.$message.error('表单校验失败')
} else {
this.$message.success('检验成功')
console.log('表单要提交的数据:', JSON.parse(JSON.stringify(this.dynamicFormData)))
}
},
}
}
</script>
<style scoped>
.p-title {
font-size: 16px;
font-weight: 700;
width: 88%;
height: 30px;
line-height: 30px;
background: #d9d9d9;
margin: 3px auto 10px auto;
}
</style>```