日常开发中 表单提交功能很常见 但是并不是所有表单都是简单的一层 有时候我们会有这种场景:
大表单中有一个按钮,点击按钮在大表单中增加一个小表单,这就是动态表单
如何校验这种动态表单呢,网上查找很多博客 都不是很满意 以下是我的解决方案
1.首先是页面
<uni-forms :border="true" ref="form" :rules="rules" :model="formData">
<uni-forms-item label="xxx" required name="xxx">
<uni-easyinput :trim="true" :inputBorder="false" v-model="formData.xxx"
placeholder="请输入xxx" />
</uni-forms-item>
<!-- 动态表单区域 -->
<view v-for="(item, index) in formData.xxx" :key="index">
<!-- 注意下面的 name="'xxx'+index" 其中xxx是this.formDate.xxx[index].xxx属性
name必须对应rules的属性名
-->
<uni-forms-item label="文字文字" required type="number" :name="'xxx'+index">
<uni-easyinput @blur="blurSj" @input="inputSjchange"
:inputBorder="false"
v-model="formData.rule[index]['xxx']" placeholder="请输入xxx" />
</uni-forms-item>
<uni-forms-item label="文字文字1" required type="number" :name="'xxx1'+index">
<uni-easyinput @blur="blurSj1" @input="inputSjchange1"
:inputBorder="false"
v-model="formData.rule[index]['xxx1']" placeholder="请输入xxx1" />
</uni-forms-item>
</uni-forms>
<view class="addbtn"><text @tap="add">+ 添加动态表单</text></view>
<view @click="submit('submit')"> 保存 </view>
2.其次是逻辑
<script>
export default {
name: "",
data() {
return {
id:'',
formData: {
'xxx':'',
'xxx': {
'Dtarr': [
{
'xxx':'',
'xxx1':''
}
],
}
},
rules: {
xxx: {
rules: [{
required: true,
errorMessage: '请输入xxx',
trigger: 'blur'
},
{
validateFunction: (rule, value, data, callback) => {
let isInteger = /^\+?[1-9][0-9]*$/
let legal = isInteger.test(Number(value))
if (!legal) {
callback('请填写正确的件数格式')
}
return true
}
},
]
},
xxx1: {
rules: [{
required: true,
errorMessage: '请输入xxx1',
trigger: 'blur'
}, {
validateFunction: (rule, value, data, callback) => {
let isInteger = /^\+?[1-9][0-9]*$/
let isPosflopoinum = /^(([1-9]\d*)(\.\d{1,2})?)$|(0\.0?([1-9]\d?))$/
let legal = isInteger.test(Number(value)) || isPosflopoinum.test(Number(value))
if (!legal) {
callback('请填写正确的运费格式')
}
return true
}
}]
},
},
isInteger: /^\+?[1-9][0-9]*$/,
isPosflopoinum: /^(([1-9]\d*)(\.\d{1,2})?)$|(0\.0?([1-9]\d?))$/,
}
},
onReady() {
this.getTransportList()
this.$refs.form.setRules(this.rules);
},
methods: {
blurSj(e) {
for (let key in this.formData.Dtarr) {
let legal = this.isInteger.test(Number(this.formData.rule[key].snum))
if (!legal) {
this.formData.rule[key].xxx= ''
}
}
},
blurSj1(e) {
for (let key in this.formData.Dtarr) {
let legal = this.isInteger.test(Number(this.formData.rule[key].snum))
if (!legal) {
this.formData.rule[key].xxx1= ''
}
}
},
inputSjchange(e) {
if (this.formData.rule[1].xxx== '' || 0) {
this.formData.rule[1].xxx= ''
} else {
this.formData.rule[1].xxx= Number(this.formData.rule[1].xxx) + 1
this.formData.rule[1].xxx= Number(this.formData.rule[1].xxx) - 1
}
},
inputSjchange1(e) {
if (this.formData.rule[1].xxx1== '' || 0) {
this.formData.rule[1].xxx1= ''
} else {
this.formData.rule[1].xxx1= Number(this.formData.rule[1].xxx1) + 1
this.formData.rule[1].xxx1= Number(this.formData.rule[1].xxx1) - 1
}
},
getTransportList() {
let params= {
id: this.id
}
this.$api.getdetail(params).then(res => {
if (res.code == 200) {
this.formData= res.data;
let validate = this.rules['xxx1']
this.formData.xxx[0].forEach((items, index) => {
this.rules['xxx' + index] = validate
})
}
})
},
submit(ref) {
let query = {
...
};
this.$refs.form.validate(this.formData).then(res => {
if (this.id== null || this.id== '') {
that.showLoading('加载中', true)
that.$api.addDtform(query).then(res => {
if (res.code == 200) {
that.showMsg('添加成功!')
that.hideLoading();
} else {
that.showMsg(res.msg)
that.hideLoading()
}
})
} else {
query.id = that.id;
that.$api.addDtform(query).then(res => {
that.showLoading('加载中', true)
if (res.code == 200) {
that.showMsg('修改成功!')
that.hideLoading();
} else {
that.showMsg(res.msg)
that.hideLoading()
}
})
}
})
},
add() {
let item = {
'XXX':'',
'XXX1':''
};
this.formData.XXX[0].push(item)
let validate = that.rules['xxx1']
this.formDate.xxx[0].forEach((items, index) => {
this.rules['xxx' + index] = validate
})
this.$forceUpdate(this.rules)
}
}
}
</script>
总结:
- 代码中我用的是for in 去循环数组的 因为我之前写的动态表单是个对象 前面的索引是从1开始 页面用v-for循环也是从索引 1 开始循环的 介意的话可以全使用foreach 其他 但是用for in 去循环数组也没啥问题 我只是懒得改了;
- 主要的bug就是uniapp这些表单不会自动校验 或者说是不会校验第二次就很恶心,所以我在输入框绑定的两个input和blur事件来处理 算是歪门邪道 但也是解决bug的关键方法 ;
- 其实在h5中都是可以使用自定义校验表单的格式的 但是微信小程序端不会识别 uniapp官方文档好像有说过 具体用啥正则可以自行去看 我这边就直接绑定blur去判断格式的
- 在h5中我们甚至可以在uni-forms-item标签中绑定 rule ,但是在微信小程序中直接报错 所以如果只有h5端 这种方法还简单一点 有微信小程序端的话 添加 编辑时都要动态增加校验规则
<uni-forms-item label="文字文字" required type="number" :name="'xxx'+index">
<uni-easyinput @input="inputSjchange"
:inputBorder="false"
:rule = "[{required: true,errorMessage: '请输入xxx'},{validateFunction: validatexxxfun}]"
v-model="formData.rule[index]['xxx']" placeholder="请输入xxx" />
</uni-forms-item>