vue3+antdesign3.2.20版本实现可编辑表格及校验

在工作中经常会遇到可编辑表格加校验功能,这里根据我遇到的问题分享给大家解决方案,踩了很多坑,希望对你有帮助的话能点个赞。

注意:如果表格数据是一次性拿到的,那么需要arrIndex来帮助确定当前行,(我就是这种情况)

           如果数据是通过分页接口请求拿到的,那么涉及到arrIndex属性的地方都可以删除arrIndex

效果图:当点击确定的时候进行表单校验,禁用状态的学科组单元格不进行校验,

              当选择的教研室类型不是国家级教研室,则禁用学科组并清除该行校验效果。

 <a-form :model="vroomList" ref="formRef" :rules="rules">
        <a-table ref="tableRef" :pagination="pagination" :dataSource="vroomList" :columns="columns">
          <template #headerCell="{title,column}">
            <div class="custom-table-title">
              <span v-if="isShowRequiredIcon(column.dataIndex)" class="required-icon">*</span>
              <span class="title">{{title}}</span>
            </div>
          </template>

          <template #bodyCell="{ column, record,index }">
            <!-- 教研室名称 -->
            <template v-if="column.dataIndex === 'name'">
              <!-- 如果你的表格数据是接口请求拿到的,并且分页也是通过请求,那么name用这种写法:name="[index,'name']",
其他校验同理 -->
              <a-form-item :name="[arrIndex+index,'name']" :rules="rules.name">
                <a-input v-model:value="record.name" placeholder="请输入教研室名称" allowClear/>
              </a-form-item>
            </template>


            <!-- 教研室类型 -->
            <template v-if="column.dataIndex === 'vroomType'">
              <a-form-item :name="[arrIndex+index,'vroomType']" :rules="rules.vroomType">
                <a-select
                    v-model:value="record.vroomType"
                    :options="vroomTypeList"
                    :field-names="{ label: 'name' , value: 'code' }"
                    @change="vroomTypeChange($event,record,arrIndex+index)"
                    placeholder="请选择教研室类型"
                    :allow-clear="true"
                />
              </a-form-item>
            </template>

            <!-- 学科组 -->
            <template v-if="column.dataIndex === 'subjectGroupId'">
              <a-form-item :name="[arrIndex+index,'subjectGroupId']" 
:rules="[{validator: (rule,value)=>validateSubjectGroup(rule,value,record), trigger: 'change' }]">
                <a-select
                    <!-- 我这里是联动校验,当选择的教研室不是国家级,则会禁用学科组并且清除该行学科组的校验 -->
                    :disabled="record.isDisabledSubjectGroup"
                    v-model:value="record.subjectGroupId"
                    :options="subjectGroupList"
                    :field-names="{label:'subjectGroupName',value:'subjectGroupId'}"
                    placeholder="请选择学科协作组"
                />
              </a-form-item>
            </template>

            <template v-if="column.dataIndex==='action'">
              <div>
                <a-popconfirm title="确定要删除吗?" @confirm=delTap(record.customKey)>
                  <a>删除</a>
                </a-popconfirm>
              </div>
            </template>

          </template>
        </a-table>
      </a-form>

<script lang="ts">
// 导入各种包、组件啥的

const columns = [
  {
    title: "教研室名称",
    dataIndex: "name",
    align: "center",
    width: 300,
    fixed:"left"
  },
  {
    title: "教研室类型",
    dataIndex: "vroomType",
    align: "center",
    width: 280
  },
  {
    title: "学科组",
    dataIndex: "subjectGroupId",
    width: 240
  },
  {
    title: "操作",
    dataIndex: "action",
    align: "center",
    width: 100,
    fixed:"right"
  },
];
export default defineComponent({
  name: "EditVrooms",
  components: {},
  props:{
    vroomList:{
        type:array,
        default:()=>[]
    }
},
  emits:[],
  setup(props,{emit}) {
    const state = reactive({
      vroomList: [],          // 表格数据 
      vroomTypeList:[],      // 教研室分类
      subjectGroupList: [],   // 学科协作组
      arrIndex: 0, // 数组索引,用于确定页码的当前行
      注意:这里如果表格数据(vroomList)是接口请求拿到的,可以不用这个变量,上面模板绑定的name也不用这个变量,
如果数据是外部传进来的(一次性拿到的数据),这个变量必须要,因为在分页的时候第一页的index和其他页的index是一样的,
arrIndex用来确定是第几页第几行
    })

    // 自定义校验学科组,当禁用的时候不校验,返回成功的promise
    const validateSubjectGroup = (rule,value,record) => {
      if(value || record.isDisabledSubjectGroup){
        return Promise.resolve()
      }
      return Promise.reject("请选择学科组")
    }

    const rules = {
      name: [{ required: true, message: '请输入教研室名称' }],
      vroomType: [{ required: true, message: '请选择教研室类型' }],
      subjectGroupId: [{ required: true, validator:validateSubjectGroup, message: '请选择学科组' }],
    };

    // 这里是分页的配置项,如果你的数据是一次性拿到的,那么这里需要配置,如果是通过分页接口请求拿到的,
那么这里的onChange函数就需要改成调用接口请求的逻辑,并且涉及到arrIndex 属性的代码都可以删除
    const pagination = reactive({
      current: 1, // 初始页码
      pageSize: 10,
      showSizeChanger: false,
      total:state.localVroomList.length,
      showTotal:()=> `共 ${state.localVroomList.length} 条`,
      onChange:(current,pageSize)=>{
        pagination.current = current
        state.arrIndex = (current-1) *  pageSize
      }
    })

    // 这里用来控制表格标题是否显示必填 * 图标
    const showRequiredList = ["action"]
    const isShowRequiredIcon = (dataIndex) => {
      return !showRequiredList.includes(dataIndex)
    }


    // 我这里的vroomList是一次性拿到的数据,需要计算总页数,如果你全选最后一页删除,组件会自动减少一页,
但是注意:pagination的current不会-1,所以下面的方法主动调用了一下来计算当前是第几页,主要目的是为了更新arrIndex,
保证编辑行更改数据或者校验不会出问题。
    // 如果你的分页数据是通过接口请求,那么这里和下面的更新方法都可以删除
    const totalPages = computed(()=> {
      return Math.ceil(state.vroomList.length / pagination.pageSize);
    })

    // 处理当删除最后一页时current不会更新问题,这会导致校验行不对
    const updateCurrentPageIndex = () => {
      if (pagination.current > totalPages.value) {
        pagination.current = totalPages.value;
      }
      pagination.onChange(pagination.current,pagination.pageSize)
    }


    // 选择教研室类型
    const vroomTypeChange = (vroomType,record,index) => {
      record.subjectGroupId = null
      // 这里选择的不是国家级教研室则给当前行学科组添加一个禁用标识
      record.isDisabledSubjectGroup = !(vroomType === VroomTypeEnum.NationalLevel)
      if(!(vroomType === VroomTypeEnum.NationalLevel)){
        // 这个地方必须这样写,用[[]]双数组,否则其他写法都不生效
        formRef.value.clearValidate([[(state.arrIndex+index),"subjectGroupId"]]);
      }
    }


    // 获取导入列表
    const getList = () => {
      state.vroomList= cloneDeep(props.vroomList)
      state.vroomList.forEach((item,index)=>{
        item.isDisabledSubjectGroup = item.vroomType !== VroomTypeEnum.NationalLevel
        item.customKey = "key" + index
      })
    }

    onMounted(()=>{
      getList()
      getSubjectGroupList() // 学科组
      getVroomTypeList()    // 教研室类型
    })

    return {
      rules,
      ...toRefs(state),
      formRef,
      columns,
      pagination,
      isShowRequiredIcon,
      vroomTypeChange,
      validateSubjectGroup
    };
  },
});
</script>
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值