Skip to content

Commit

Permalink
修复必填表单项校验 BUG #3
Browse files Browse the repository at this point in the history
  • Loading branch information
0604hx committed Mar 11, 2024
1 parent b309931 commit 6f431a5
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 42 deletions.
6 changes: 5 additions & 1 deletion packages/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import TableWidget from "./widgets/table.vue"
* @property {String} _value - 表单项默认值
* @property {Boolean} _watch - 是否监听变化
* @property {Boolean} _container - 是否为容器
* @property {String} category - 容器类型
* @property {Array<FormItem>} items - 子表单项
* @property {Boolean} _required - 是否为必填项目
* @property {String} _regex - 请填写正则表达式(仅限勾选必填)
* @property {String} _message - 当校验失败时提示的内容(仅限勾选必填)
*/


Expand Down Expand Up @@ -145,7 +149,7 @@ export function buildOptions(text, valueField="value", labelField="label") {
throw Error(`${text} 不是有效的 options 数据内容,请参考文档进行配置`)

return options.map(o=> {
// if(typeof(o) === 'object') return o
if(typeof(o) === 'object') return o

let i = o.indexOf("|")
let obj = {}
Expand Down
96 changes: 62 additions & 34 deletions packages/common/render.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { ref, reactive, toRaw, unref, onMounted, computed, nextTick, watch } fro

import { triggerLoaded, triggerBeforeSubmit, triggerChanged, triggerExtraButtonClick, formValueProvider, extendFormItems } from './runtime'

const DEFAULT_ACTION = "post"
const DEFAULT_ACTION= "post"
const MULTIPLE = "multiple"
const SIMPLE = "simple"
const SINGLE = "single"

const buildPrefix = (p,name)=> Array.of(p, name).filter(v=>!!v).join(".")

export const RenderProps = {
renders:{type:Object},
Expand All @@ -21,10 +26,6 @@ export default (props, emits, suffix="")=>{
let inited = ref(false)
const formData = reactive({ _disabled:false })

/**
* 当表单项设置为必填时,会向该对象赋值
*/
const formRequired = {}
const watchFields = new Set()

/**
Expand Down Expand Up @@ -56,33 +57,63 @@ export default (props, emits, suffix="")=>{
// track("表单数据更新", formData, v)
// })

const _checkRequire = formObj=>{
if(props.review){
//进行表单项校验
let fails = []
Object.keys(formRequired).forEach(key=>{
let { regex, msg, label } = formRequired[key]
if(!formObj[key]) fails.push(`${label}${key})未填写`)
/**
* 检测必填项
* 子表单(非 SIMPLE)必填无法正常检测
* https://github.com/0604hx/grid-form/issues/3
*
* @param {Array<import('.').FormItem>} items - 表单定义项
* @param {Object} bean - 与 items 对应的数据对象
* @param {Array<String>} fails - 错误清单
* @param {String} prefix - 前缀文本
*/
const _checkRequire = (items, bean, fails, prefix="")=>{
for(const item of items){
if(item._container === true){
switch(item.category){
case SINGLE:
_checkRequire(item.items, bean[item._uuid]||{}, fails)
break
case MULTIPLE:
const rows = bean[item._uuid]
if(Array.isArray(rows)){
for (let i = 0; i < rows.length; i++) {
const row = rows[i]
_checkRequire(item.items, row, fails, `[${item._text||item.title}的第${i+1}条]`)
}
}
break
default:
_checkRequire(item.items, bean, fails)
}
}
else if(item._required == true){
//检查必填表单项是否符合预期
if(!bean[item._uuid])
fails.push(`${prefix}${item._text}${item._uuid})未填写`)
else{
if(!!regex && !RegExp(regex).test(formObj[key])) {
fails.push(msg||`${label}${key})校验未通过`)
}
if(!!item._regex && !RegExp(item._regex).text(bean[item._uuid]))
fails.push(prefix+(item._message || `${item._text}${item._uuid})校验未通过:${item._regex}`))
}
})

if(fails.length){
props.debug && track(`[表单检查]`, fails)
return emits("failed", fails)
}
}
return true
}

const _submitDo = (formObj, action=DEFAULT_ACTION) =>{
delete formObj['_disabled']

if(_checkRequire(formObj) === true)
emits("submit", formObj, action)
const fails = []

//校验错误字段
if(props.review == true)
_checkRequire(props.form.items, formObj, fails)

if(fails.length){
props.debug && track(`[表单检查]`, fails)
return emits("failed", fails)
}

emits("submit", formObj, action)
}

/**
Expand Down Expand Up @@ -156,7 +187,7 @@ export default (props, emits, suffix="")=>{
* 递归计算表单初始值
* @param {Array<import('.').FormItem>} items
*/
const _initFormValue = async (items, bean)=>{
const _initFormValue = async (items, bean, prefix="")=>{
if(Array.isArray(items)){
for (const v of items) {
if(!!v._uuid){
Expand All @@ -170,20 +201,17 @@ export default (props, emits, suffix="")=>{
}
bean[v._uuid] = itemV

if(v._required === true){
formRequired[v._uuid] = { regex: v._regex, msg: v._message, label: v._text }
}
if(v._watch === true)
watchFields.add(v._uuid)
}
if(v._container===true){
//默认为简单布局容器
v.category = v.category||"simple"
if(v.category == 'single') bean[v._uuid] = {}
v.category = v.category||SIMPLE
if(v.category == SINGLE) bean[v._uuid] = {}
//对于多行表单,赋予初始值
else if(v.category == 'multiple') bean[v._uuid] = []
else if(v.category == MULTIPLE) bean[v._uuid] = []

await _initFormValue(v.items, v.category == 'simple'? bean: bean[v._uuid])
await _initFormValue(v.items, v.category == SIMPLE? bean: bean[v._uuid], )
}
}
}
Expand Down Expand Up @@ -253,7 +281,7 @@ export default (props, emits, suffix="")=>{

return {
_raw, track,
inited, formData, formRequired,
inited, formData,
toSubmit, onExtraBtn
}
}
Expand All @@ -275,7 +303,7 @@ export const ContainerProps = {
* @returns
*/
export const ContainerMixin = props=>{
const isMultiple = computed(()=> props.form._container === true && props.form.category === "multiple")
const isMultiple = computed(()=> props.form._container === true && props.form.category === MULTIPLE)

const canAdd = computed(()=> {
if(!isMultiple.value) return false
Expand All @@ -284,7 +312,7 @@ export const ContainerMixin = props=>{
})

const childForm = item=>{
return !item.category || item.category == 'simple'? props.formData : props.formData[item._uuid]
return !item.category || item.category == SIMPLE? props.formData : props.formData[item._uuid]
}

const onAddRow = ()=>{
Expand Down
1 change: 1 addition & 0 deletions packages/site/components/render/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import { createForm } from "@grid-form/common"
import "."
import StudentInfo from './data/student-info.js'
import NaiveRender from './naiveui.vue'
Expand Down
2 changes: 1 addition & 1 deletion packages/site/components/render/data/student-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default {
{"_widget":"SELECT","_uuid":"type","_text":"类型", "_value":"小学", "options":"小学,中学,高中"},
{"_widget":"INPUT","_uuid":"from","_text":"开始日期"},
{"_widget":"INPUT","_uuid":"to","_text":"结束日期"},
{"_widget":"INPUT","_uuid":"school","_col":3,"_text":"学校名称"}
{"_widget":"INPUT","_uuid":"school","_col":3,"_text":"学校名称", "_required":true }
]
}
],
Expand Down
2 changes: 0 additions & 2 deletions packages/site/components/render/elementplus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import { FormRender, RenderFuncs } from "@grid-form/render-element"
import { RenderDemo } from "."
const props = defineProps({
form: {type:Object, default:{}},
onSubmit: {type:Function},
Expand Down
2 changes: 0 additions & 2 deletions packages/site/components/render/naiveui.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import { FormRender, RenderFuncs } from "@grid-form/render-naive"
import { RenderDemo } from "."
const props = defineProps({
form: {type:Object, default:{}},
onSubmit: {type:Function},
Expand Down
2 changes: 0 additions & 2 deletions packages/site/components/render/vant4.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import { useData } from 'vitepress'
import { RenderDemo } from "."
const { isDark } = useData()
const props = defineProps({
Expand Down

0 comments on commit 6f431a5

Please sign in to comment.