elementUI动态嵌套el-form表单校验
一、基础表单校验
前端项目开发过程中表单校验是非常常见的需求,elementUI的el-form组件也是支持配置rules属性来配置表单项的校验。
Form 组件允许你验证用户的输入是否符合规范,来帮助你找到和纠正错误。
Form 组件提供了表单验证的功能,只需为 rules 属性传入约定的验证规则,并将 form-Item 的 prop 属性设置为需要验证的特殊键值即可。
例如:
不要漏掉el-from-item的prop
属性,需要和rules对象
中的属性字段对应。
定义rules对象:
提交表单时验证规则:
校验是通过调用表单实例(表单组件上的ref属性绑定的变量
)上的validate方法
来实现的(异步)
这样,在我们进行验证时,如果表单项不符合rules中的规则,那么就会在对应的表单项下面提示我们设定的提示信息。
校验规则
elementUI中el-from校验的规则是引用的https://github.com/yiminghe/async-validator
比较常用的规则属性有:
必填:required
可以赋值一个boolean值,true表示必填。
类型:type
赋值有一个字符,表示要验证的内容的类型:string、number等,详情见下图:
正则验证:pattern
如果对于type无法验证的值,我们可以使用pattern赋值一个正则表达式来更加灵活的验证规则。
验证前转换:transform
有时有必要在验证之前转换一个值,可以使用tansform属性,是一个函数,参数是要验证的值,该函数的返回值
是处理后再验证的值。
例如上面代码name的校验中就用到了这几个属性,其中transform会将用户输入的内容去掉字符串首位空格(trim方法)后再进行其他规则验证。
name: {
type: 'string',
required: true,
pattern: /^[a-z]+$/,
transform(value) {
return value.trim();
},
}
二、动态嵌套表单校验
了解了基础的表单校验,那么有的时候会遇到比较复杂的表单对象,并且可能需要动态增加表单项。
elementUI官网给出了一个比较简单的例子:添加/删除表单项
在此基础上,我增加了一下表单对象的复杂度。
可以看到,domains数组每个对象下包含了info对象属性,info对象下有name和intro属性,是一个嵌套的对象,并且我们可以动态的新增和删除domains中的对象,那么在表单中该如何验证呢?
本质上,检验是通过设置的rules对象中的属性,去匹配表单项上设置的prop,然后对双向绑定的内容进行验证。
首先,我们设置rules对象:
直接按照表单对象的层级设置属性即可,因为domains数组中的对象肯定是公用一套规则的。
可以看到,我们直接循环domains数组,然后通过设置prop="'domains.' + index + '.value'"
来实现数组中的每个对象独立校验。
接着我们还要在每个表单项el-form-item上定义对应的rules,就能达到新增的表单项也能够校验的目的了。
效果:
三、示例源码
代码基于vue3 + ts,项目中如果安装并注册了elemetPlus,可以直接cv查看效果。
<template>
<div class="form-box">
<el-form ref="formRef" :model="dynamicValidateForm" label-width="120px" :rules="rules">
<div class="inner-form-box">
<el-form-item prop="email" label="Email📮">
<el-input v-model="dynamicValidateForm.email" />
</el-form-item>
</div>
<div v-for="(domain, index) in dynamicValidateForm.domains" :key="domain.key" class="inner-form-box">
<span>{{ `网站${index + 1}💌:` }}</span>
<el-form-item label="网站域名:" :prop="'domains.' + index + '.value'" :rules="rules.domains.value">
<el-input v-model="domain.value" />
</el-form-item>
<div>
<span>{{ `网站${index + 1}详情📃:` }}</span>
<el-form-item label="网站名称:" :prop="'domains.' + index + '.info.name'" :rules="rules.domains.info.name">
<el-input v-model="domain.info.name" />
</el-form-item>
<el-form-item label="网站简介:" :prop="'domains.' + index + '.info.intro'"
:rules="rules.domains.info.intro">
<el-input v-model="domain.info.intro" />
</el-form-item>
</div>
<div class="del-btn-box">
<el-button type="danger" link @click="removeDomain(domain)">删除</el-button>
</div>
</div>
<el-form-item>
<el-button type="primary" @click="submitForm(formRef)">Submit</el-button>
<el-button @click="addDomain">New domain</el-button>
<el-button @click="resetForm(formRef)">Reset</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance } from 'element-plus'
const formRef = ref<FormInstance>()
const dynamicValidateForm = reactive<{
domains: DomainItem[]
email: string
}>({
domains: [
{
key: 1,
value: '',
info: {
name: '',
intro: ''
}
},
],
email: '',
})
const rules = {
email: [
{required: true,message: '邮箱地址不能为空哦',trigger: 'blur',},
{type: 'email',message: '请输入正确的邮箱格式',trigger: ['blur', 'change'],},
],
domains: {
value: {required: true,message: '网站域名不能为空哦',trigger: 'blur',},
info: {
name: {required: true,message: '网站名称不能为空哦',trigger: 'blur',},
intro: {required: true,message: '网站简介不能为空哦',trigger: 'blur',}
}
}
}
interface DomainItem {
key: number
value: string
info: {
name: string
intro: string
}
}
const removeDomain = (item: DomainItem) => {
const index = dynamicValidateForm.domains.indexOf(item)
if (index !== -1) {
dynamicValidateForm.domains.splice(index, 1)
}
}
const addDomain = () => {
dynamicValidateForm.domains.push({
key: Date.now(),
value: '',
info: {
name: '',
intro: ''
}
})
}
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log(dynamicValidateForm)
} else {
console.log('error submit!')
return false
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
</script>
<style scoped>
.form-box {
padding: 50px;
}
.inner-form-box {
position: relative;
padding: 10px;
margin-bottom: 10px;
box-shadow: 0px 0px 5px 0px #f2f2f2;
}
.del-btn-box {
position: absolute;
right: 0;
top: 0;
transform: translateX(120%);
}
</style>
更多推荐
所有评论(0)