循环设置多个ref及多表单验证(vue3+ts)
分享小部分以前项目封装的一个动态表单
·
具体界面效果是看不到啦,以前的项目,离了后台看不到
html代码
<div class="form-list" v-if="formTableShow">
<el-form
v-for="(item, index) in formList"
:ref="(el: any) => { setItemRef(el, index)}"
:model="dataForm['form' + index]"
:rules="rules['form' + index]"
:size="formConfigs.size"
:label-width="formConfigs.labelWidth"
:inline="formConfigs.inline"
:label-position="formConfigs.labelPosition"
:disabled="formConfigs.disabled"
:status-icon="formConfigs.statusIcon"
>
<el-form-item
:label="foitem.label"
:prop="foitem.prop"
:label-width="foitem.labelWdith || 'auto'"
v-for="foitem in item.forms"
>
<el-input v-model="dataForm['form' + index][foitem.prop]"></el-input>
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button type="primary" @click="submitRule">保存</el-button>
</div>
</div>
PS: 这个分享乃以前项目封装的一个动态表单提取出来的部分,完整的很复杂,功能有以下几点:
- 同一个vue文件,展示100多种表格,表格的表头等信息全由接口返回
- 所有表格的新增、修改、查看都用同一个弹窗组件,弹窗里面有多种情况(单个表单、多个表单、多个表单和多个表格),其中表格里面也是表单可以编辑且有表单验证,每部分还可能有自己的标题,甚至某些表头或label也有tooltip提示信息
- 弹窗内所有表单/表格的所有信息(label、表头、字段、验证…)都由后端配置接口返回,部分复杂的多表单多表格内容因太复杂就由前端自己配置了
鉴于功能及其代码太复杂便不贴出来了
ts部分
<script lang="ts" setup>
import {
ref,
reactive,
computed,
} from 'vue'
import { FormRules } from 'element-plus'
interface FormItem {
prop: string // 表单字段
label: string // 表单label
labelWdith?: string // 表单宽度
formtype?: string // 表单类型
defaultValue?: any // 默认值
rule?: any // 表单验证配置
config?: any // 表单原生配置
}
// 所有表单配置----这部分是props传入的,提取后稍微改了下
const formList: any = [
{
title: 'string',
forms: [
{
// prop: 'string', // 字段 必
// label: 'string', // 表单名 必
// labelWdith: 'string', // 表单名宽度 非比 默认:auto
// rule: {} // 验证规则
// ...
},
{
// prop: 'string', // 字段 必
// label: 'string', // 表单名 必
// labelWdith: 'string', // 表单名宽度 非比 默认:auto
// rule: {} // 验证规则
// ...
}
// ....
]
},
{
title: 'string',
forms: [
{
// prop: 'string', // 字段 必
// label: 'string', // 表单名 必
// labelWdith: 'string', // 表单名宽度 非比 默认:auto
// rule: {} // 验证规则
// ...
},
{
// prop: 'string', // 字段 必
// label: 'string', // 表单名 必
// labelWdith: 'string', // 表单名宽度 非比 默认:auto
// rule: {} // 验证规则
// ...
}
// ....
]
}
]
// 表单总体配置
const formConfigs = computed(() => {
return {
size: 'default',
labelWidth: 'auto',
inline: false,
labelPosition: 'right',
disabled: false,
statusIcon: false,
...props.formConfig // 传入的表单公共配置
}
})
// 所有表单表格配置
const formTableShow = ref(false) // 为了解决动态处理验证规则后自动启动验证
const dataForm: any = ref({}) // 多套表单字段
const rules: any = reactive({}) // 多套验证规则
let resetForm = reactive({}) // 为了重置按钮的点击效果
const refList: any = reactive({}) // 多个ref
// 初始化表单
const initForm = async () => {
// 处理多套表单或者表格的dataForm和验证规则
await formList.map((item: any, index: number) => {
dataForm.value['form' + index] = {}
rules['form' + index] = <FormRules>{}
item.forms?.map((foitem: FormItem) => {
// 设置表单字段
dataForm.value['form' + index][foitem.prop] =
foitem.defaultValue === undefined
? foitem.formtype === 'inputnumber'
? undefined
: foitem.formtype === 'picker' &&
foitem.config?.type?.includes('range')
? []
: ''
: foitem.defaultValue
// 设置验证规则
if (foitem.rule?.message) {
// 验证规则
rules['form' + index][foitem.prop] = [
{
required:
foitem.rule.required === undefined ? false : foitem.rule.required,
message: foitem.rule.message || '请输入',
trigger: foitem.rule.trigger || 'blur'
}
]
}
// 获取字典
getDict(foitem)
})
})
// 初始化完成再渲染表单表格,负责验证不起效
formTableShow.value = true
// 为了重置表单
resetForm = { ...dataForm.value }
}
// 设置多个ref
const setItemRef = (el: any, index: number) => {
if (el) {
refList['ref' + index] = el
}
}
// 数据提交验证
const formRule = ref(false) // 表单是否通过,和表格相反
const submitRule = async () => {
await formList.map((item: any, index: number) => {
refList['ref' + index]?.validate((valid: any, props: any) => {
if (valid) {
formRule.value = true
} else {
formRule.value = false
}
})
})
setTimeout(() => {
// 如果都通过则提交
if (formRule.value) {
submitAll()
}
}, 100)
}
</script>
当初为了这个功能,掉了不晓得多少头发,趁空闲时间,便记录下来部分
更多推荐
已为社区贡献3条内容
所有评论(0)