elementui的动态表单的校验及动态的prop,required使用

这篇博客详细介绍了如何在HTML和JavaScript中实现动态表单的创建、编辑和验证逻辑。内容包括通过添加按钮生成新的表单组,每组内包含多个输入字段,如选择产品、输入脚本、选择投放媒体、上传视频或输入视频链接等。每个字段都有相应的验证规则,例如至少需要上传视频或输入链接。此外,还特别提到了在验证规则中自定义方法以确保一方有值时清除另一方的验证状态,避免提示信息残留的问题。整个表单支持删除除第一组外的任意一组,提供了友好的用户交互体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求及下图展示的那样,红框里是一组,通过点击右下角的添加按钮可以生成一组新的,除了第一组不能删除,后来添加的每组都可以删除,每组里面的上传视频和视频链接,二者至少有一个有值,红色星号标识为必填项。
在这里插入图片描述
正常的填写逻辑应该如下图(注意视频的字段星号的变化)
在这里插入图片描述
html代码实现:
因为每组里面的每个输入框都是循环出来的,然后每一组又是动态生成的,又是一个大循环,涉及到循环嵌套,所以html部分如下:

<el-form :model="editImgFrom" :rules="editRules" ref="videoFromRef" label-width="108px">
        <div v-for="(item, index) in editImgFrom.tableData" :key="index">
          <div class="editWriter-writerArray">
            <el-form-item label="产品:" :prop="'tableData.'+ index +'.relatedProduct'" :rules="editRules.relatedProduct">
              <el-select v-model="item.relatedProduct" clearable>
                <el-option
                  v-for="item in editProduct"
                  :key = 'item.code'
                  :value = "item.code"
                  :label = "item.name"/>
              </el-select>
            </el-form-item>
            <el-form-item class="input_240" label="所属脚本:" :prop="'tableData.'+ index +'.state'" :rules="editRules.relatedScript">
              <el-autocomplete
                v-model="item.state"
                :fetch-suggestions="(queryString,callback)=>{querySearchAsync(queryString, callback, index)}"
                placeholder="请输入内容"
                @select="(value)=>handleSelect(value, index)"
              ></el-autocomplete>
            </el-form-item>
            <el-form-item label="投放媒体:" :prop="'tableData.'+ index +'.placeMedia'" :rules="editRules.placeMedia">
              <el-checkbox-group v-model="item.checkedId" @change="checkedChange(index, item.checkedId)">
                <el-checkbox label="1">快手</el-checkbox>
                <el-checkbox label="2">腾讯</el-checkbox>
                <el-checkbox label="3">头条</el-checkbox>
              </el-checkbox-group>
            </el-form-item>
            <el-form-item label="上传视频:" :prop="'tableData.'+index+'.content'" :rules="editRules.content" :required="!item.externalVideoLinks">
              <el-button @click="openVideoDialog(index)" v-if="!item.content">上传视频</el-button>
              <video v-else :src="`${BASEURL}${item.content}`" class="avatar" controls="controls">您的浏览器不支持视频播放</video>
              <el-button v-if="item.content" @click="openVideoDialog(index)" type="text">替换视频</el-button>
            </el-form-item>
            <el-form-item label="视频链接:" :prop="'tableData.'+ index +'.externalVideoLinks'" :rules="editRules.externalVideoLinks" :required="!item.content">
              <el-input v-model="item.externalVideoLinks" clearable :maxlength='200'/>
            </el-form-item>
            <el-button type="primary" class="del_btn" style="margin-left:110px;" @click="delCurrentRow(index)" v-show="index>0">删除</el-button>
          </div>
        </div>
        <div class="editWriter-tabButtom">
          <el-button @click="addRows">添加</el-button>
        </div>
      </el-form>
    </div>
    <div class="editWriter-footer">
      <el-button @click="submitClick">保存</el-button>     
    </div>

注意**:prop="'tableData.'+ index +'.externalVideoLinks'":required="!item.content"**的写法。

js部分:

data(){
    const _this=this;
    let validvideo=(rule,value,callback)=>{
        let newArr=rule.field.split('.')
        let currentIndex=newArr[1];
        let currentProp=newArr[2];
        let currentPropBro='';
        if(currentProp==='externalVideoLinks'){
          currentPropBro=this.editImgFrom.tableData[currentIndex].content;
        }else{
          currentPropBro=this.editImgFrom.tableData[currentIndex].externalVideoLinks;
        }
        if(value===''&&currentPropBro===''){
          callback(new Error('请上传视频或输入视频链接'))
        }else{
          _this.$refs['videoFromRef'].clearValidate('tableData.'+ currentIndex + '.externalVideoLinks');
          _this.$refs['videoFromRef'].clearValidate('tableData.'+ currentIndex + '.content');
          callback()
        }
    	};
    return {
      editImgFrom: {
        tableData: [
          {
            content: '', //视频url
            relatedScript: '', //关联脚本id
            relatedProduct: '', //关联产品id
            placeMedia: '', //投放媒体,逗号分割(1:快手,2:腾讯,3:头条)
            userId: '', //用户id
            checkedId: [],
            externalVideoLinks:'',//视频链接
          }
        ]
      },
      editRules: {
        relatedProduct: [{required: true, message: '请选择产品', trigger: 'change'}],
        placeMedia: [{required: true, message: '请选择投放媒体', trigger: 'change'}],
        content: [{validator:validvideo,message: '请上传视频', trigger:['change','blur']}],
       externalVideoLinks: [{validator:validvideo,message: '请输入视频链接', trigger:['change','blur']}],
      },
      editProduct:[],
      scriptInputList: [],
    }
  },
  methods:{
  submitClick(handleType){
      let vm = this;
      vm.$refs['videoFromRef'].validate((valid)=>{
        if(valid){
          //此处写验证通过后的提交逻辑
          
        }else{
          vm.$TopTip({ message: '存在必填项未填写' });
          return false;
        }
      })
    },
}

注意在rules里不要写required:true,data方法里自定义验证规则时,当一方有值,要记得清除验证。否则可能会出现英文提示或者输入完之后再删除提示语残留的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值