找回密码
 立即注册
首页 业界区 业界 在elementui,antDesign,antDesignVue中表格嵌套多个表单 ...

在elementui,antDesign,antDesignVue中表格嵌套多个表单项校验

锟及 2025-6-23 01:45:55
前言

在此记录下使用 elementui,antDesign,antDesignVue 的表格嵌套表单校验的一些经验。
要达到的目的是:有个多行表格,每一行有多个表单项(比如输入框),表单项填完值后,点击提交,校验表格中所有表单项,校验通过则将整个表格数据送到后台。还可以重新给表格赋值(比如进入详情页面)。效果如下:
1.gif

正文

elementui 和 elementPlus 使用方式一样,这里就只用 elementui 来举例,版本是 2.x。
antDesignVue 1.x 版本有两种表单校验方式,v-decorator 和 FormModel ,要达到上面的效果需要用 FormModel 的方式,而后面 2.x 及以后的版本将两种方式合并,统一用 FormModel 的方式。
antDesign 我这里用的 3.x 版本,用的是 getFieldDecorator 方式,并且是函数式组件的写法。
<blockquote>
需要注意的是如果使用的是 react@ {        console.log('表格数据',JSON.parse(JSON.stringify(this.asdfform)));        if (valid) {        }      });    },    resetTableData() {      this.asdfform.rows = [        { key: 1, name: `Edrward ${1}`, age: "1234", address: "1234" },        { key: 2, name: `Edrward ${2}`, age: "1234", address: "1234" },        { key: 3, name: `Edrward ${3}`, age: "", address: "" },        { key: 4, name: `Edrward ${4}`, age: "4", address: "44" },      ];    },  },[/code]完整示例
antDesignVue 1.x 用法

如果用的是FormModel 方式,那么写法和 elementui 中一样,不过需要先引入
  1. :prop="'rows.'+scope.$index+'.age'"
  2. v-model.trim="asdfform.rows[scope.$index].age"
复制代码
页面中使用
  1. <el-form :model="asdfform" ref="asdfform" label-width="20px">
  2.     <el-table :data="asdfform.rows">
  3.         <el-table-column prop="name" label="name"></el-table-column>
  4.         <el-table-column prop="age" label="age">
  5.             <template slot-scope="scope">
  6.                 <el-form-item label=" " :rules="[{required: true, message:'请输入'}]" :prop="'rows.'+scope.$index+'.age'">
  7.                     <el-input v-model.trim="asdfform.rows[scope.$index].age"></el-input>
  8.                 </el-form-item>
  9.             </template>
  10.         </el-table-column>
  11.         <el-table-column prop="address" label="address">
  12.             <template slot-scope="scope">
  13.                 <el-form-item label=" " :rules="[{required:true,message:'请输入'}]" :prop="'rows.'+ scope.$index + '.address'">
  14.                     <el-input v-model.trim="asdfform.rows[scope.$index].address"></el-input>
  15.                 </el-form-item>
  16.             </template>
  17.         </el-table-column>
  18.     </el-table>
  19. </el-form>
  20. <el-button type="primary" size="small" @click="handleSubmit">表单提交</el-button>
  21. <el-button type="danger" size="small" @click="resetTableData">重新给表格赋值</el-button>
复制代码
  1. data() {
  2.     return {
  3.       asdfform: {
  4.         rows: [
  5.           { key: 1, name: `Edrward ${1}`, age: "1234", address: "1234" },
  6.           { key: 2, name: `Edrward ${2}`, age: "1234", address: "1234" },
  7.           { key: 3, name: `Edrward ${3}`, age: "", address: "" },
  8.         ],
  9.       },
  10.     };
  11.   },
  12.   methods: {
  13.     handleSubmit() {
  14.       this.$refs.asdfform.validate((valid) => {
  15.         console.log('表格数据',JSON.parse(JSON.stringify(this.asdfform)));
  16.         if (valid) {
  17.         }
  18.       });
  19.     },
  20.     resetTableData() {
  21.       this.asdfform.rows = [
  22.         { key: 1, name: `Edrward ${1}`, age: "1234", address: "1234" },
  23.         { key: 2, name: `Edrward ${2}`, age: "1234", address: "1234" },
  24.         { key: 3, name: `Edrward ${3}`, age: "", address: "" },
  25.         { key: 4, name: `Edrward ${4}`, age: "4", address: "44" },
  26.       ];
  27.     },
  28.   },
复制代码
antDesign 3.x 用法

react 中没有 v-model 的用法,这里通过 setState + useEffect 来实现。
vue 中使用 asdfform 定义表单数据,asdfform.rows 定义表格数据,也就是表格数据是嵌套在表单数据里面的,所以表单项改变,表格数据也会同步改变。
react 中表格数据和表单数据的分开维护的,所以当表格数据改变时,需要在 useEffect 里面同步表单数据,同样表单数据变化后,提交函数中也会创建一份新的表格数据。
1、定义基本结构
这里使用了 Form.create 和 getFieldDecorator 的方式校验表单。
经 Form.create() 包装过的组件会自带 this.props.form 属性。
使用 Form.create 处理后的表单具有自动收集数据并校验的功能,但如果您不需要这个功能,或者默认的行为无法满足业务需求,可以选择不使用 Form.create 并自行处理数据。
  1. import { FormModel } from 'ant-design-vue'
  2. Vue.use(FormModel)
复制代码
2、添加表格列,根据需要自定义列内容
  1.     index"
  2.     >
  3.         <template slot="age" slot-scope="text,record, index">
  4.             
  5.                
  6.             </a-form-model-item>
  7.         </template>
  8.         <template slot="address" slot-scope="text,record,index">
  9.             
  10.                
  11.             </a-form-model-item>
  12.         </template>
  13.     </a-table>
  14.    
  15.         Submit</a-button>
  16.     </a-form-item>
  17. </a-form-model>
复制代码
3、添加提交函数和重置数据函数(给表格重新赋值)
  1. data: function () {
  2.     return {
  3.         asdfform: {
  4.             rows: [
  5.                 { key: 1, name: `Edrward ${1}`, age: '1234', address: '1234' },
  6.                 { key: 2, name: `Edrward ${2}`, age: '1234', address: '1234' },
  7.                 { key: 3, name: `Edrward ${3}`, age: '', address: '' },
  8.             ]
  9.         },
  10.         asdfcolumns: [
  11.             { title: 'name', dataIndex: 'name', width: '25%' },
  12.             {
  13.                 title: 'age',
  14.                 dataIndex: 'age',
  15.                 width: '15% ',
  16.                 scopedSlots: { customRender: 'age' }
  17.             },
  18.             {
  19.                 title: 'address',
  20.                 dataIndex: 'address',
  21.                 width: '40%',
  22.                 scopedSlots: { customRender: 'address' }
  23.             },
  24.             { title: 'operation', dataIndex: 'operation' },
  25.         ],
  26.     }
  27. },
  28. methods: {
  29.     handleSubmit() {
  30.         this.$refs.asdfform.validate(valid => {
  31.             console.log(this.asdfform)
  32.             if (valid) { }
  33.         });
  34.     }
  35. }
复制代码
  1. const App = ({ form }) => {
  2.     const { getFieldDecorator, setFieldsValue, validateFields } = form;
  3.    
  4.     // 定义表格数据
  5.     const [data, setData] = useState([
  6.         { key: 1, name: `Edrward ${1}`, age: "1234", address: "1234" },
  7.         { key: 2, name: `Edrward ${2}`, age: "1234", address: "1234" },
  8.         { key: 3, name: `Edrward ${3}`, age: "", address: "" },
  9.     ]);
  10.     return (
  11.         <>
  12.           <Form>
  13.             <Table
  14.               columns={asdfcolumns}
  15.               dataSource={data}
  16.               pagination={false}
  17.               rowKey="key"
  18.             ></Table>
  19.             <Form.Item>
  20.               <Button type="primary" onClick={handleSubmit}>
  21.                 Submit
  22.               </Button>
  23.               <Button onClick={handleReset}>reset</Button>
  24.             </Form.Item>
  25.           </Form>
  26.         </>
  27.     );
  28. }
  29. const WrappedMyFormComponent = Form.create()(App);
  30. export default WrappedMyFormComponent;
复制代码
4、表格数据改变后同步更新表单
  1. const asdfcolumns = [
  2.     { title: "name", dataIndex: "name", width: "25%" },
  3.     {
  4.       title: "age",
  5.       dataIndex: "age",
  6.       width: "15%",
  7.       render: (text, record, index) => (
  8.         <Form.Item>
  9.           {getFieldDecorator(`data.${index}.age`, {
  10.             rules: [{ required: true, message: "请输入" }],
  11.             initialValue: record["age"],
  12.           })(<Input />)}
  13.         </Form.Item>
  14.       ),
  15.     },
  16.     {
  17.       title: "address",
  18.       dataIndex: "address",
  19.       width: "40%",
  20.       render: (text, record, index) => (
  21.         <Form.Item>
  22.           {getFieldDecorator(`data.${index}.address`, {
  23.             rules: [
  24.               {
  25.                 required: true,
  26.                 message: "请输入!",
  27.               },
  28.             ],
  29.             initialValue: record["address"],
  30.           })(<Input />)}
  31.         </Form.Item>
  32.       ),
  33.     },
  34.     { title: "operation", dataIndex: "operation" },
  35. ];
复制代码
antDesign 的完整代码
  1. import { Button, Form, Input, Table } from "antd";import { useEffect, useState } from "react";const App = ({ form }) => {  const { getFieldDecorator, setFieldsValue, validateFields } =    form;  const asdfcolumns = [    { title: "name", dataIndex: "name", width: "25%" },    {      title: "age",      dataIndex: "age",      width: "15%",      render: (text, record, index) => (                  {getFieldDecorator(`data.${index}.age`, {            rules: [{ required: true, message: "请输入" }],            initialValue: record["age"],          })()}              ),    },    {      title: "address",      dataIndex: "address",      width: "40%",      render: (text, record, index) => (                  {getFieldDecorator(`data.${index}.address`, {            rules: [              {                required: true,                message: "请输入!",              },            ],            initialValue: record["address"],          })()}              ),    },    { title: "operation", dataIndex: "operation" },  ];  const [data, setData] = useState([    { key: 1, name: `Edrward ${1}`, age: "1234", address: "1234" },    { key: 2, name: `Edrward ${2}`, age: "1234", address: "1234" },    { key: 3, name: `Edrward ${3}`, age: "", address: "" },  ]);  const handleSubmit = () => {    validateFields((err, values) => {      if (!err) {        console.log("Received values of form: ", values);        const updatedData = data.map((item, index) => ({                ...item,                age: values.data[index].age,                address: values.data[index].address,        }));        console.log(updatedData);      }    });  };  const App = ({ form }) => {
  2.     const { getFieldDecorator, setFieldsValue, validateFields } = form;
  3.    
  4.     // 定义表格数据
  5.     const [data, setData] = useState([
  6.         { key: 1, name: `Edrward ${1}`, age: "1234", address: "1234" },
  7.         { key: 2, name: `Edrward ${2}`, age: "1234", address: "1234" },
  8.         { key: 3, name: `Edrward ${3}`, age: "", address: "" },
  9.     ]);
  10.     return (
  11.         <>
  12.           <Form>
  13.             <Table
  14.               columns={asdfcolumns}
  15.               dataSource={data}
  16.               pagination={false}
  17.               rowKey="key"
  18.             ></Table>
  19.             <Form.Item>
  20.               <Button type="primary" onClick={handleSubmit}>
  21.                 Submit
  22.               </Button>
  23.               <Button onClick={handleReset}>reset</Button>
  24.             </Form.Item>
  25.           </Form>
  26.         </>
  27.     );
  28. }
  29. const WrappedMyFormComponent = Form.create()(App);
  30. export default WrappedMyFormComponent;  const asdfcolumns = [
  31.     { title: "name", dataIndex: "name", width: "25%" },
  32.     {
  33.       title: "age",
  34.       dataIndex: "age",
  35.       width: "15%",
  36.       render: (text, record, index) => (
  37.         <Form.Item>
  38.           {getFieldDecorator(`data.${index}.age`, {
  39.             rules: [{ required: true, message: "请输入" }],
  40.             initialValue: record["age"],
  41.           })(<Input />)}
  42.         </Form.Item>
  43.       ),
  44.     },
  45.     {
  46.       title: "address",
  47.       dataIndex: "address",
  48.       width: "40%",
  49.       render: (text, record, index) => (
  50.         <Form.Item>
  51.           {getFieldDecorator(`data.${index}.address`, {
  52.             rules: [
  53.               {
  54.                 required: true,
  55.                 message: "请输入!",
  56.               },
  57.             ],
  58.             initialValue: record["address"],
  59.           })(<Input />)}
  60.         </Form.Item>
  61.       ),
  62.     },
  63.     { title: "operation", dataIndex: "operation" },
  64. ];  return (                  [table][/table]                              Submit                    reset                    );};const WrappedMyFormComponent = Form.create()(App);export default WrappedMyFormComponent;
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册