vue + element 动态渲染、移除表单并添加验证
博客地址:https://ainyi.com/66
又接到新需求了吧~~
背景
在一个大表单里,有可能会出现这种需求,用户可以自己操作动态添加、移除表单,更加个性化的效果。
常见于填写个人信息、附加内容的表单
例如:
“工作经历”可以用户自己点击继续添加按钮,在原有的表单后面 append 多一个表单,不需要就点击右上方 X 按钮移除
问题
在实现之前,提出几个问题
- vue 怎么动态渲染或移除表单上去
- v-model 怎么绑定动态添加表单的 value 值
- 动态新增的表单如何验证
- 动态表单怎么填写对应的 prop
...
好吧,我当时也思考了一会,最后选择数组方式,动态渲染
代码实现讲解
利用数组,v-for 循环方式,可以完美实现动态渲染和移除,因为操作的只有对象数组而已
请格外注意动态添加表单的 rule 和 prop
每个动态添加的表单都要加上 rule
prop 需要根据对象数组下标绑定设置对应的 value(:prop="'azList[' + index + '].azName'")
<div class="section-form" v-for="(item, index) in form.azList" :key="index">
<span v-if="isShowCloseBtn" class="close" @click="deleteItem(index)">
<i class="el-icon-close"></i>
</span>
<el-form-item label="可用区名称:"
:rules="[{ required: true, message: '可用区名称不能为空' }]"
:prop="'azList[' + index + '].azName'"
label-width="150px">
<el-input placeholder="请输入可用区名称" v-model="item.azName" :maxlength="30"></el-input>
</el-form-item>
<el-form-item label="逻辑可用区编码:"
:rules="[{ required: true, message: '逻辑可用区编码不能为空' }]"
label-width="150px"
:prop="'azList[' + index + '].logicCode'">
<el-input placeholder="请输入唯一ID" v-model="item.logicCode" :maxlength="30"></el-input>
</el-form-item>
<el-form-item label="物理可用区编码:"
:rules="[{ required: true, message: '物理可用区编码不能为空' }]"
label-width="150px"
:prop="'azList[' + index + '].physicCode'">
<el-input placeholder="请输入唯一ID" v-model="item.physicCode" :maxlength="30"></el-input>
</el-form-item>
</div>
那么对应的 js 代码为
export default {
name: 'vouchersDetail',
data() {
return {
form: {
regionName: '',
regionCode: '',
// 动态添加的对象数组
azList: [
{
azName: '',
logicCode: '',
physicCode: ''
}
]
}
}
},
computed: {
// 至少保留一个动态表单的开关
isShowCloseBtn() {
return this.form['azList'].length > 1
}
},
methods: {
addItem() {
// 点击添加表单的按钮,只需要将表单绑定的 value 作为对象 push 到对象数组
this.form['azList'].push({
azName: '',
logicCode: '',
physicCode: '',
weight: ''
})
},
deleteItem(index) {
// 点击移除表单的按钮,根据点击的当前 index 移除对象数组的元素
this.form['azList'].splice(index, 1)
},
goBack() {
window.history.back(-1)
}
}
}
更新
19号更新,分离组件方法,写法更简便,易维护,还可以将校验规则剥离出去
根据上面的方法 利用数组,v-for 循环方式
此次更新,关键在于,是父组件引用子组件的 template 循环
v-for 循环数组的 item 对象传入子组件 template
每个子组件的 form 的 :model = 传入的 item,也就不需要用到数组下标 index,每个子组件是独立的一个 form,也就是说,每个动态添加字段的校验规则可以剥离出去了
父组件
template 循环
<create-region
class="section-form"
ref="refCreateAz"
:infoData="item"
:indexNum="index"
:isShowCloseBtn="isShowCloseBtn"
v-for="(item, index) in form.azList"
:key="index"
@deleteItem="deleteItem">
</create-region>
js 与原来无差,只是多了引入子组件的 component
components: {
CreateRegion: () => import('@/views/region/models/CreateRegion')
}
子组件
<template>
<el-form :model="infoData" :rules="rulesAz" label-width="150px" ref="formAz">
<span v-if="isShowCloseBtn" class="close" @click="deleteItem">
<i class="el-icon-close"></i>
</span>
<el-form-item label="可用区名称:" prop="azName" label-width="150px">
<el-input placeholder="请输入可用区名称" v-model="infoData.azName" :maxlength="30"></el-input>
</el-form-item>
<el-form-item label="逻辑可用区编码:" label-width="150px" prop="logicCode">
<el-input placeholder="请输入唯一ID" v-model="infoData.logicCode" :maxlength="30"></el-input>
</el-form-item>
<el-form-item label="物理可用区编码:" label-width="150px" prop="physicCode">
<el-input placeholder="请输入唯一ID" v-model="infoData.physicCode" :maxlength="30"></el-input>
</el-form-item>
<el-form-item label="权重设置:" label-width="150px">
<el-input placeholder="请设置权重" v-model="infoData.weight"></el-input>
</el-form-item>
</el-form>
</template>
<script>
import { ORGION_AZLIST_RULES } from '@/views/service/rules'
export default {
props: {
infoData: {
require: true
},
indexNum: {
type: Number
},
isShowCloseBtn: {
type: Boolean
}
},
data() {
return {
form: this.infoData,
rulesAz: ORGION_AZLIST_RULES.call(this)
}
},
computed: {},
methods: {
deleteItem() {
this.$emit('deleteItem', this.indexNum)
},
validates() {
return new Promise((resolve, reject) => {
this.$refs['formAz'].validate(async valid => {
if (valid) {
// 验证通过
resolve(true)
} else {
reject(false)
}
})
})
}
}
}
</script>
校验
export const ORGION_AZLIST_RULES = function() {
return {
logicCode: [
{
required: true,
message: '逻辑可用区编码不能为空',
trigger: 'blur'
},
{
validator: CHECK_AZEXITS_CODE.bind(this),
trigger: 'blur'
}
],
physicCode: [
{
required: true,
message: '物理可用区编码不能为空',
trigger: 'blur'
},
{
validator: CHECK_AZEXITS_CODE.bind(this),
trigger: 'blur'
}
],
azName: [
{
required: true,
message: '可用区名称不能为空',
trigger: 'blur'
}
]
}
}
自定义校验
export const CHECK_AZEXITS_CODE = async function(rule, value, callback) {
let paramName = rule.field
let reqData = {}
reqData[paramName] = value
let { result } = await getAzExist(reqData)
if (result.result) {
if (paramName === 'logicCode') {
callback(new Error('逻辑可用区编码已存在,请重新输入'))
} else {
callback(new Error('物理可用区编码已存在,请重新输入'))
}
} else {
callback()
}
}
写在后面
如果大家有啥更好的方法实现,欢迎在评论区相互探讨~
写完下班、
博客地址:https://ainyi.com/66
vue + element 动态渲染、移除表单并添加验证的更多相关文章
- v-if案例解析(element-ui form-item 结合 v-if 动态生成rule规则\表单元素,表单无法验证问题剖析 )
fire 读在最前面: 1.此文章衔接Vue 虚拟Dom 及 部分生命周期初探,相关整体知识点请先阅读后再继续本文阅读 问:当v-if为true时,会重新渲染相关dom节点吗? <child v ...
- 如何在.Net Core MVC中为动态表单开启客户端验证
非Core中的请参照: MVC的验证 jquery.validate.unobtrusive mvc验证jquery.unobtrusive-ajax 参照向动态表单增加验证 页面引入相关JS: &l ...
- vue同一页面中拥有两个表单时,验证问题
问题:如果vue的同一个页面拥有两个表单.验证第一个表单时没有通过就切换到第二个,那么第二个表单会出现验证错误的信息 我们可以通过为两个表单添加ref属性 之后在通过调用resetFields()方法 ...
- 使用CSS来渲染HTML的表单元素
效果: 实现: <!DOCTYPE html> <html> <head> <title>使用CSS来渲染HTML的表单元素</title> ...
- Element Ui使用技巧——Form表单的校验规则rules详细说明
Element UI中对Form表单验证的使用介绍: Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item的 prop 属性设置为需校验的字段名 ...
- 第一百八十六节,jQuery,验证表单插件,Ajax 表单插件,验证和提交表单
jQuery,验证表单插件,Ajax 表单插件,验证和提交表单 HTML <form id="reg" method="post" action=&quo ...
- 推荐几款很棒的 JavaScript 表单美化和验证插件
表单元素让人爱恨交加.作为网页最重要的组成部分,表单几乎无处不在,从简单的邮件订阅.登陆注册到复杂的需要多页填写的信息提交功能,表单都让开发者花费了大量的时间和精力去处理,以期实现好用又漂亮的表单功能 ...
- form表单的ajax验证2
form表单的ajax验证2: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...
- 在Tomcat中采用基于表单的安全验证
.概述 (1)基于表单的验证 基于From的安全认证可以通过TomcatServer对Form表单中所提供的数据进行验证,基于表单的验证使系统开发者可以自定义用户的登陆页面和报错页面.这种验证方法 ...
随机推荐
- Android P Beta发布!最新版本抢先体验!
在不久前结束的谷歌I/O开发者大会上,谷歌公布了下一个版本的 Android,也就是 Android P 的 beta 版本.Android P 将 AI 定位为操作系统的核心,并侧重于提供智能且简洁 ...
- C语言实现十六进制字符串转数字
代码: int StringToInt(char *hex) { ]) * + CharToInt(hex[]); } int CharToInt(char hex) { ') '; if (hex& ...
- 『zkw线段树及其简单运用』
阅读本文前,请确保已经阅读并理解了如下两篇文章: 『线段树 Segment Tree』 『线段树简单运用』 引入 这是一种由\(THU-zkw\)大佬发明的数据结构,本质上是经典的线段树区间划分思想, ...
- Promise原理—一步一步实现一个Promise
promise特点 一个promise的当前状态只能是pending.fulfilled和rejected三种之一.状态改变只能是pending到fulfilled或者pending到rejected ...
- MySQL 上手教程
安装 通过官网选择版本下载安装.Mac 上可通过 Homebrew 方便地安装: $ brew install mysql 检查安装是否成功: $ mysql --version mysql Ver ...
- 深入解读Service Mesh的数据面Envoy
在前面的一篇文章中,详细解读了Service Mesh中的技术细节,深入解读Service Mesh背后的技术细节. 但是对于数据面的关键组件Envoy没有详细解读,这篇文章补上. 一.Envoy的工 ...
- C# Memory Cache 踩坑记录
背景 前些天公司服务器数据库访问量偏高,运维人员收到告警推送,安排我团队小伙伴排查原因. 我们发现原来系统定期会跑一个回归测试,该测运行的任务较多,每处理一条任务都会到数据库中取相关数据,高速地回归测 ...
- RIP 实验
一.环境准备 1. 软件:GNS3 2. 路由:c7200 二.实验操作 实验要求: 1. 理解 RIP 协议的工作原理 2. 理解 RIPv1.RIPv2 的特性 3. 掌握 RIP 协议的基本配置 ...
- Android版数据结构与算法(四):基于哈希表实现HashMap核心源码彻底分析
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 存储键值对我们首先想到HashMap,它的底层基于哈希表,采用数组存储数据,使用链表来解决哈希碰撞,它是线程不安全的,并且存储的key只能有一个为 ...
- webapi 跨域问题
参考:http://www.cnblogs.com/chenxizhang/p/3821703.html 给自己做个笔记 HttpContext.Current.Response.AddHeader( ...