Element Plus,基于 Vue 3,面向设计师和开发者的组件库
Element Plus 官网:https://element-plus.org/zh-CN/
Element Plus Form 动态表单自定义效验规则,官网示例代码中没有,官网示例中的动态表单是固定的规则,本文讲解动态表单自定义规则的使用
目录
1、官网动态表单示例代码
先看官网动态表单示例代码
<template>
<el-form
ref="formRef"
:model="dynamicValidateForm"
label-width="120px"
class="demo-dynamic"
>
<el-form-item
prop="email"
label="Email"
:rules="[
{
required: true,
message: 'Please input email address',
trigger: 'blur',
},
{
type: 'email',
message: 'Please input correct email address',
trigger: ['blur', 'change'],
},
]"
>
<el-input v-model="dynamicValidateForm.email" />
</el-form-item>
<el-form-item
v-for="(domain, index) in dynamicValidateForm.domains"
:key="domain.key"
:label="'Domain' + index"
:prop="'domains.' + index + '.value'"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input v-model="domain.value" />
<el-button class="mt-2" @click.prevent="removeDomain(domain)"
>Delete</el-button
>
</el-form-item>
<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>
</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: '',
},
],
email: '',
})
interface DomainItem {
key: number
value: 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: '',
})
}
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!')
return false
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
</script>
运行效果
这个是把 rules 写死在 el-form-item 标签上的
2、表单自定义规则
官网的自定义规则是在 el-form 标签上添加 rules 属性,并在 rules 属性中定义自定义规则,el-form-item 标签通过 prop 属性对应找到规则
官网示例代码
<template>
<el-form
ref="ruleFormRef"
:model="ruleForm"
status-icon
:rules="rules"
label-width="120px"
class="demo-ruleForm"
>
<el-form-item label="Password" prop="pass">
<el-input v-model="ruleForm.pass" type="password" autocomplete="off" />
</el-form-item>
<el-form-item label="Confirm" prop="checkPass">
<el-input
v-model="ruleForm.checkPass"
type="password"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="Age" prop="age">
<el-input v-model.number="ruleForm.age" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(ruleFormRef)"
>Submit</el-button
>
<el-button @click="resetForm(ruleFormRef)">Reset</el-button>
</el-form-item>
</el-form>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
const ruleFormRef = ref<FormInstance>()
const checkAge = (rule: any, value: any, callback: any) => {
if (!value) {
return callback(new Error('Please input the age'))
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('Please input digits'))
} else {
if (value < 18) {
callback(new Error('Age must be greater than 18'))
} else {
callback()
}
}
}, 1000)
}
const validatePass = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('Please input the password'))
} else {
if (ruleForm.checkPass !== '') {
if (!ruleFormRef.value) return
ruleFormRef.value.validateField('checkPass', () => null)
}
callback()
}
}
const validatePass2 = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('Please input the password again'))
} else if (value !== ruleForm.pass) {
callback(new Error("Two inputs don't match!"))
} else {
callback()
}
}
const ruleForm = reactive({
pass: '',
checkPass: '',
age: '',
})
const rules = reactive<FormRules<typeof ruleForm>>({
pass: [{ validator: validatePass, trigger: 'blur' }],
checkPass: [{ validator: validatePass2, trigger: 'blur' }],
age: [{ validator: checkAge, trigger: 'blur' }],
})
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!')
return false
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
</script>
运行效果
3、动态表单自定义规则
动态表单自定义规则就是将动态表单和自定义规则结合,在 el-form-item 标签属性 rules 上添加自定义规则
3.1、单字段动态表单
看下面代码
<template>
<el-form
ref="formRef"
:model="dynamicValidateForm"
label-width="120px"
class="demo-dynamic"
>
<el-form-item
prop="email"
label="Email"
:rules="[
{
required: true,
message: 'Please input email address',
trigger: 'blur',
},
{
type: 'email',
message: 'Please input correct email address',
trigger: ['blur', 'change'],
},
]"
>
<el-input v-model="dynamicValidateForm.email" />
</el-form-item>
<el-form-item
v-for="(domain, index) in dynamicValidateForm.domains"
:key="domain.key"
:label="'Domain' + index"
:prop="'domains.' + index + '.value'"
:rules="[
{
required: true,
message: 'domain can not be null',
trigger: 'blur',
},
{ validator: validatePass, trigger: 'blur' }
]"
>
<el-input v-model="domain.value" />
<el-button class="mt-2" @click.prevent="removeDomain(domain)"
>Delete</el-button
>
</el-form-item>
<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>
</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: '',
},
],
email: '',
})
interface DomainItem {
key: number
value: 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: '',
})
}
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!')
return false
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
const validatePass = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('Please input the password'))
} else {
if (value.length > 5) {
callback(new Error('密码长度不能超过5'))
}
callback()
}
}
</script>
运行效果
3.2、多字段动态表单
<template>
<el-form
ref="formRef"
:model="dynamicValidateForm"
label-width="120px"
class="demo-dynamic"
>
<el-form-item
prop="email"
label="Email"
:rules="[
{
required: true,
message: 'Please input email address',
trigger: 'blur',
},
{
type: 'email',
message: 'Please input correct email address',
trigger: ['blur', 'change'],
},
]"
>
<el-input v-model="dynamicValidateForm.email" />
</el-form-item>
<template v-for="(domain, index) in dynamicValidateForm.domains" :key="domain.key">
<el-form-item
:label="'Domain' + index"
:prop="'domains.' + index + '.value'"
:rules="[
{
required: true,
message: 'domain can not be null',
trigger: 'blur',
},
{ validator: validatePass, trigger: 'blur' }
]"
>
<el-input v-model="domain.value" />
</el-form-item>
<el-form-item
:label="'Name' + index"
:prop="'domains.' + index + '.name'"
:rules="[
{
required: true,
message: 'domain can not be null',
trigger: 'blur',
},
{ validator: validateName, trigger: 'blur' }
]"
>
<el-input v-model="domain.name" />
<el-button class="mt-2" @click.prevent="removeDomain(domain)">Delete</el-button>
</el-form-item>
</template>
<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>
</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: '',
name: ''
},
],
email: '',
})
interface DomainItem {
key: number
value: 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: '',
name: '',
})
}
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!')
return false
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
const validatePass = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('Please input the password'))
} else {
if (value.length > 5) {
callback(new Error('密码长度不能超过5'))
}
callback()
}
}
const validateName = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('name 不能为空'))
} else {
if (value.length > 10) {
callback(new Error('name长度不能超过10'))
}
callback()
}
}
</script>
运行效果
4、总结
动态表单自定义效验规则,是将官网 rules 对象改成数组后,添加自定义规则即可,这种方式同样适用于 View UI Plus,下面是 View UI Plus 代码
<template>
<Form ref="formDynamic" :model="formDynamic" :label-width="80" style="width: 300px">
<template v-for="(item, index) in formDynamic.items">
<FormItem
v-if="item.status"
:key="index"
:label="'Item ' + item.index"
:prop="'items.' + index + '.value'"
:rules="[
{required: true, message: 'Item ' + item.index +' can not be empty', trigger: 'blur'},
{ validator: validatePassCheck, trigger: 'blur' }
]">
<Row>
<Col span="18">
<Input type="text" v-model="item.value" placeholder="Enter something..."></Input>
</Col>
<Col span="4" offset="1">
<Button @click="handleRemove(index)">Delete</Button>
</Col>
</Row>
</FormItem>
</template>
<FormItem>
<Row>
<Col span="12">
<Button type="dashed" long @click="handleAdd" icon="md-add">Add item</Button>
</Col>
</Row>
</FormItem>
<FormItem>
<Button type="primary" @click="handleSubmit('formDynamic')">Submit</Button>
<Button @click="handleReset('formDynamic')" style="margin-left: 8px">Reset</Button>
</FormItem>
</Form>
</template>
<script>
export default {
data () {
return {
index: 1,
formDynamic: {
items: [
{
value: '',
index: 1,
status: 1
}
]
}
}
},
methods: {
handleSubmit (name) {
this.$refs[name].validate((valid) => {
if (valid) {
this.$Message.success('Success!');
} else {
this.$Message.error('Fail!');
}
})
},
handleReset (name) {
this.$refs[name].resetFields();
},
handleAdd () {
this.index++;
this.formDynamic.items.push({
value: '',
index: this.index,
status: 1
});
},
handleRemove (index) {
this.formDynamic.items[index].status = 0;
},
validatePassCheck(rule, value, callback) {
if (value === '') {
callback(new Error('Please enter your password again'));
} else if (value.length > 5) {
callback(new Error('密码长度不能大于5'));
} else {
callback();
}
}
}
}
</script>
运行效果
至此完