antd+vue3对循环的表单控件添加自定义校验

对循环的表单控件添加自定义校验

 


效果如下:

 

 

 

 代码如下:

复制代码
  1 <template>
  2   <a-form ref="formRef" :model="modelRef" v-bind="outLayout" class="layout">
  3     <a-form-item
  4       v-for="(domain, index) in modelRef.domains"
  5       :key="domain.key"
  6       v-bind="itemLayout"
  7       :label="'步骤' + (index + 1)"
  8       :name="['domains', index, 'value']"
  9       :rules="[
 10         {
 11           required: true,
 12           message: '步骤内容不能为空',
 13         },
 14         {
 15           max: 200,
 16           message: '最多输入200字,请重新输入',
 17         },
 18       ]"
 19     >
 20       <a-textarea
 21         v-model:value.trim="domain.value"
 22         placeholder="请输入(200字以内)"
 23         style="width: 50%; margin-right: 8px"
 24       />
 25       <MinusCircleOutlined
 26         v-if="modelRef.domains.length > 1"
 27         class="dynamic-delete-button"
 28         :disabled="modelRef.domains.length === 1"
 29         @click="removeDomain(domain)"
 30       />
 31     </a-form-item>
 33     <a-form-item v-bind="outLayout">
 34       <a-button type="dashed" style="width: 55%" @click="addDomain">
 35         <PlusOutlined />
 36         新增步骤
 37       </a-button>
 38     </a-form-item>
 39 
 40     <a-button class="hidden" @click="onSubmit" />
 41   </a-form>
 42 </template>
 43 <script>
 44 import { reactive, toRefs, watch } from 'vue'
 45 import { cloneDeep } from 'lodash'
 46 import { shareState } from './model'
 47 
 48 export default {
 49   setup() {
 50     const state = reactive({
 51       formRef: null, 53       itemLayout: {
 54         labelCol: { span: 2 },
 55         wrapperCol: { span: 15 },
 56       },
 57       outLayout: {
 58         wrapperCol: {
 59           span: 14,
 60           offset: 2,
 61         },
 62       },
 63     })
 64     const modelRef = reactive({
 65       domains: [],
 66     })
 67 
     // 初始化 控件值 68 const initData = async () => { 69 const data = cloneDeep(shareState.formData.recipeStepList) 70 modelRef.domains = data.map(v => { 71 return { value: v, key: Date.now() + Math.random() } 72 }) 73 } 74 75 watch( 76 () => shareState.formData, 77 val => { 78 if (val) initData() 79 }, 80 { deep: true, immediate: true }, 81 ) 82
     // 删除输入框 83 const removeDomain = item => { 84 const index = modelRef.domains.indexOf(item) 85 if (index !== -1) { 86 modelRef.domains.splice(index, 1) 87 } 88 } 89
     // 添加输入框 90 const addDomain = () => { 92 modelRef.domains.push({ 93 value: null, 94 key: Date.now() + Math.random(), 95 }) 96 } 97
     // 由于此模块作为组件被引入到其他页面(父组件),父组件有一个统一的保存按钮,点击此按钮时触发该onSubmit事件,以此校验该表单是否填写正确 98 const onSubmit = () => { 99 return state.formRef 100 .validate() 101 .then(() => { 107 const arr = modelRef.domains.map(v => v.value) 108 const data = arr.join('#') 109 return Promise.resolve(data) 110 }) 111 .catch(error => { 112 return Promise.reject(new Error(error)) 113 }) 114 } 115 116 return { 117 ...toRefs(state), 118 modelRef, 119 onSubmit, 120 removeDomain, 121 addDomain, 122 } 123 }, 124 } 125 </script> 126 <style lang="less" scoped> 127 .layout { 128 .dynamic-delete-button { 129 cursor: pointer; 130 position: relative; 131 top: 4px; 132 font-size: 24px; 133 color: #999; 134 transition: all 0.3s; 135 } 136 .dynamic-delete-button:hover { 137 color: #777; 138 }145 :deep(.ant-col-offset-2) { 146 margin-left: 6.5%; 147 } 148 :deep(.ant-col-2) { 149 max-width: 6.5%; 150 } 151 } 152 </style>
复制代码

 

posted @   ke乐  阅读(2383)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示