antDesign Vue 实现表单嵌套表格,可以添加和删除,校验

  • 实现功能

1. 可以添加行、删除行

2. 可以实现输入时,校验输入内容,在点击确定时,校验整体格式

注意:

1.name属性是:name="['dataSource', index, 'name']",整个form绑定的是formData,table绑定的是formData.dataSource。

2. v-model:value="record['name']" ,record是这行数据

      <a-form ref="tableFormRef" :model="formData" :label-col="{ style: { width: '100px' } }" :wrapper-col="{ span: 0 }"
        autocomplete="off">
        <a-form-item label="通知名称" :rules="rulesCheck.warnName" name="warnName">
          <a-input v-model:value="formData.warnName"></a-input>
        </a-form-item>
        <a-form-item label="通知方式" :rules="rulesCheck.value1" name="value1">
          <a-checkbox-group v-model:value="formData.value1" :options="plainOptions">
          </a-checkbox-group>
        </a-form-item>
        <a-form-item label="添加一行">
          <a-button size="small" @click="addRow">
            <template #icon>
              <PlusOutlined />
            </template>
          </a-button>
        </a-form-item>
        <a-table class="ant-table-striped" bordered :dataSource="formData.dataSource" :columns="tableColumns"
          :pagination="false">
          <template #bodyCell="{ column, text, record, index }">
            <template v-if="column.dataIndex == 'name'">
              <a-form-item  :name="['dataSource', index, 'name']"
                :rules="rulesCheck.name">
                <a-input  v-model:value="record['name']"></a-input>
              </a-form-item>
            </template>
            <template v-if="column.dataIndex == 'iphone'">
              <a-form-item  :name="['dataSource', index, 'iphone']"
                :rules="rulesCheck.iphone">
                <a-input  v-model:value="record[column.dataIndex]"></a-input>
              </a-form-item>
            </template>
            <template v-if="column.dataIndex == 'email'">
              <a-form-item  v-model:value="record[column.dataIndex]"
                :rules="rulesCheck.email" :name="['dataSource', index, 'email']">
                <a-input  v-model:value="record[column.dataIndex]"></a-input>
              </a-form-item>
            </template>
            <template v-if="column.dataIndex == 'operation'">
              <a-button size="small" @click="delRow(index)">
                <template #icon>
                  <CloseOutlined />
                </template>
              </a-button>
            </template>
          </template>
        </a-table>
        <a-button @click="ok">确定</a-button>
        <a-button @click="cancel">取消</a-button>
      </a-form>
  </div>
</template>
  • fromData格式

注意:formData里面dataSource里面是表单校验,其他是其他表单组件

let formData: any = ref({
  dataSource: [{ name: "", iphone: "", email: "" }],
  warnName: "",
  value1: ["10", "01"],
  warnProbability: ["", ""],
});

function addRow() {
  formData.value.dataSource.push({ name: "", iphone: "", email: "" });
}
function delRow(index) {
  formData.value.dataSource.splice(index, 1);
}



//点击确定时调用组件方法即可。tableFormRef.value.validate()

//这里有个缺陷,本来想使用validateFields校验部分对应字段,如选择邮箱,就校验姓名和邮箱

tableFormRef.value.validateFields(['name','email'])

但是不生效,我理解的是该方法会校验formData.dataSource,
它不会校验formData.dataSource里面的name和email,

所有我采用折中的方案,如果只选择了其中一种,通过遍历formData.dataSource的值,进行一个弹窗展示。

 完整代码

<template>
  <div style="width: 800px;padding: 100px;">
      <a-form ref="tableFormRef" :model="formData" :label-col="{ style: { width: '100px' } }" :wrapper-col="{ span: 0 }"
        autocomplete="off">
        <a-form-item label="通知名称" :rules="rulesCheck.warnName" name="warnName">
          <a-input v-model:value="formData.warnName"></a-input>
        </a-form-item>
        <a-form-item label="通知方式" :rules="rulesCheck.value1" name="value1">
          <a-checkbox-group v-model:value="formData.value1" :options="plainOptions">
          </a-checkbox-group>
        </a-form-item>
        <a-form-item label="添加一行">
          <a-button size="small" @click="addRow">
            <template #icon>
              <PlusOutlined />
            </template>
          </a-button>
        </a-form-item>
        <a-table class="ant-table-striped" bordered :dataSource="formData.dataSource" :columns="tableColumns"
          :pagination="false">
          <template #bodyCell="{ column, text, record, index }">
            <template v-if="column.dataIndex == 'name'">
              <a-form-item  :name="['dataSource', index, 'name']"
                :rules="rulesCheck.name">
                <a-input  v-model:value="record['name']"></a-input>
              </a-form-item>
            </template>
            <template v-if="column.dataIndex == 'iphone'">
              <a-form-item  :name="['dataSource', index, 'iphone']"
                :rules="rulesCheck.iphone">
                <a-input  v-model:value="record[column.dataIndex]"></a-input>
              </a-form-item>
            </template>
            <template v-if="column.dataIndex == 'email'">
              <a-form-item  v-model:value="record[column.dataIndex]"
                :rules="rulesCheck.email" :name="['dataSource', index, 'email']">
                <a-input  v-model:value="record[column.dataIndex]"></a-input>
              </a-form-item>
            </template>
            <template v-if="column.dataIndex == 'operation'">
              <a-button size="small" @click="delRow(index)">
                <template #icon>
                  <CloseOutlined />
                </template>
              </a-button>
            </template>
          </template>
        </a-table>
        <a-button @click="ok">确定</a-button>
        <a-button @click="cancel">取消</a-button>
      </a-form>
  </div>
</template>
<script setup lang="ts">
import { ref, } from "vue";
import { modleRuleColumns } from "./model.data";
import { PlusOutlined, CloseOutlined } from "@ant-design/icons-vue";
import { rulesCheck } from "@/utils/rules";
let tableColumns = ref(modleRuleColumns);
// 表单校验
const tableFormRef = ref();
const plainOptions = [
  { label: "短信", value: "10" },
  { label: "邮箱", value: "01" },
];

let formData: any = ref({
  dataSource: [{ name: "", iphone: "", email: "" }],
  warnName: "",
  value1: ["10", "01"],
  warnProbability: ["", ""],
});

function addRow() {
  formData.value.dataSource.push({ name: "", iphone: "", email: "" });
}
function delRow(index) {
  formData.value.dataSource.splice(index, 1);
}
async function ok() {
  if (formData.value.dataSource.length == 0) {
    alert("至少添加一条数据");
    return;
  }
  let checkStr = formData.value.value1.join(" ");
  if (!checkStr) {
    alert("请至少选择一种通知方式");
    return;
  }
  // 全校验 全选
  if (checkStr.indexOf(" ") > -1) {
    tableFormRef.value.validate().then(() => {
      //调用接口执行下一步

  });
    return;
  }
  // 短信校验 邮箱校验
  if (checkStr == "10" || checkStr == "01") {
    // 无法校验指定form
    // tableFormRef.value.validateFields(["email", "name"])
    console.log("getErrorList()", getErrorList());
    if (getErrorList()) {
      console.log('getErrorList()',getErrorList());
      alert('提示')
      return;
    }
    //校验通过后,执行方法
  }
}
function getErrorList() {
  // 11 邮箱和手机号 只考虑:01邮箱 10短信
  // getPushType()
  let filterFlag: string[] = [];
  if (getPushType() == "01") {
    filterFlag = ["email", "name"];
  }
  if (getPushType() == "10") {
    filterFlag = ["iphone", "name"];
  }
  let result = [] as any;
  formData.value.dataSource.map((el, idx) => {
    if (!el[filterFlag[0]] || !el[filterFlag[1]]) {
      el.index = idx + 1;
      result.push(el);
    }
  });
  if (result.length > 0) {
    let info = "";
    result.forEach((el) => {
      info += `第${el.index}行需要填写${!el.name ? "姓名," : ""}${!el.iphone ? "手机号," : ""}${!el.email ? "邮箱" : ""}</br>`;
    });
    return info;
  }
}
function cancel(){
}
function getPushType() {
  let checkStr = formData.value.value1.join(" ");
  if (checkStr && checkStr.indexOf(" ") > -1) {
    return "11";
  }
  return checkStr;
}
</script>

 

export const modleRuleColumns = [
  {
    title: '序号',
    dataIndex: 'index',
    width: 80,
    customRender: ({ index }) => { return index + 1 }
  },
  {
    title: '姓名',
    dataIndex: 'name',
    width: 150,
  },
  {
    title: '手机号',
    dataIndex: 'iphone',
    width: 150,

  },
  {
    title: '邮箱',
    dataIndex: 'email',
    width: 150,
  },
  {
    title: '操作',
    dataIndex: 'operation',
    width: 80,
    align: "center"
  },
]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值