前言
在此记录下使用 elementui,antDesign,antDesignVue 的表格嵌套表单校验的一些经验。
要达到的目的是:有个多行表格,每一行有多个表单项(比如输入框),表单项填完值后,点击提交,校验表格中所有表单项,校验通过则将整个表格数据送到后台。还可以重新给表格赋值(比如进入详情页面)。效果如下:
正文
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 中一样,不过需要先引入- :prop="'rows.'+scope.$index+'.age'"
- v-model.trim="asdfform.rows[scope.$index].age"
复制代码 页面中使用- <el-form :model="asdfform" ref="asdfform" label-width="20px">
- <el-table :data="asdfform.rows">
- <el-table-column prop="name" label="name"></el-table-column>
- <el-table-column prop="age" label="age">
- <template slot-scope="scope">
- <el-form-item label=" " :rules="[{required: true, message:'请输入'}]" :prop="'rows.'+scope.$index+'.age'">
- <el-input v-model.trim="asdfform.rows[scope.$index].age"></el-input>
- </el-form-item>
- </template>
- </el-table-column>
- <el-table-column prop="address" label="address">
- <template slot-scope="scope">
- <el-form-item label=" " :rules="[{required:true,message:'请输入'}]" :prop="'rows.'+ scope.$index + '.address'">
- <el-input v-model.trim="asdfform.rows[scope.$index].address"></el-input>
- </el-form-item>
- </template>
- </el-table-column>
- </el-table>
- </el-form>
- <el-button type="primary" size="small" @click="handleSubmit">表单提交</el-button>
- <el-button type="danger" size="small" @click="resetTableData">重新给表格赋值</el-button>
复制代码- data() {
- return {
- 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: "" },
- ],
- },
- };
- },
- methods: {
- handleSubmit() {
- this.$refs.asdfform.validate((valid) => {
- 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" },
- ];
- },
- },
复制代码 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 并自行处理数据。
- import { FormModel } from 'ant-design-vue'
- Vue.use(FormModel)
复制代码 2、添加表格列,根据需要自定义列内容- index"
- >
- <template slot="age" slot-scope="text,record, index">
-
-
- </a-form-model-item>
- </template>
- <template slot="address" slot-scope="text,record,index">
-
-
- </a-form-model-item>
- </template>
- </a-table>
-
- Submit</a-button>
- </a-form-item>
- </a-form-model>
复制代码 3、添加提交函数和重置数据函数(给表格重新赋值)- data: function () {
- return {
- 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: '' },
- ]
- },
- asdfcolumns: [
- { title: 'name', dataIndex: 'name', width: '25%' },
- {
- title: 'age',
- dataIndex: 'age',
- width: '15% ',
- scopedSlots: { customRender: 'age' }
- },
- {
- title: 'address',
- dataIndex: 'address',
- width: '40%',
- scopedSlots: { customRender: 'address' }
- },
- { title: 'operation', dataIndex: 'operation' },
- ],
- }
- },
- methods: {
- handleSubmit() {
- this.$refs.asdfform.validate(valid => {
- console.log(this.asdfform)
- if (valid) { }
- });
- }
- }
复制代码- const App = ({ form }) => {
- const { getFieldDecorator, setFieldsValue, validateFields } = form;
-
- // 定义表格数据
- 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: "" },
- ]);
- return (
- <>
- <Form>
- <Table
- columns={asdfcolumns}
- dataSource={data}
- pagination={false}
- rowKey="key"
- ></Table>
- <Form.Item>
- <Button type="primary" onClick={handleSubmit}>
- Submit
- </Button>
- <Button onClick={handleReset}>reset</Button>
- </Form.Item>
- </Form>
- </>
- );
- }
- const WrappedMyFormComponent = Form.create()(App);
- export default WrappedMyFormComponent;
复制代码 4、表格数据改变后同步更新表单- const asdfcolumns = [
- { title: "name", dataIndex: "name", width: "25%" },
- {
- title: "age",
- dataIndex: "age",
- width: "15%",
- render: (text, record, index) => (
- <Form.Item>
- {getFieldDecorator(`data.${index}.age`, {
- rules: [{ required: true, message: "请输入" }],
- initialValue: record["age"],
- })(<Input />)}
- </Form.Item>
- ),
- },
- {
- title: "address",
- dataIndex: "address",
- width: "40%",
- render: (text, record, index) => (
- <Form.Item>
- {getFieldDecorator(`data.${index}.address`, {
- rules: [
- {
- required: true,
- message: "请输入!",
- },
- ],
- initialValue: record["address"],
- })(<Input />)}
- </Form.Item>
- ),
- },
- { title: "operation", dataIndex: "operation" },
- ];
复制代码 antDesign 的完整代码- 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 }) => {
- const { getFieldDecorator, setFieldsValue, validateFields } = form;
-
- // 定义表格数据
- 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: "" },
- ]);
- return (
- <>
- <Form>
- <Table
- columns={asdfcolumns}
- dataSource={data}
- pagination={false}
- rowKey="key"
- ></Table>
- <Form.Item>
- <Button type="primary" onClick={handleSubmit}>
- Submit
- </Button>
- <Button onClick={handleReset}>reset</Button>
- </Form.Item>
- </Form>
- </>
- );
- }
- const WrappedMyFormComponent = Form.create()(App);
- export default WrappedMyFormComponent; const asdfcolumns = [
- { title: "name", dataIndex: "name", width: "25%" },
- {
- title: "age",
- dataIndex: "age",
- width: "15%",
- render: (text, record, index) => (
- <Form.Item>
- {getFieldDecorator(`data.${index}.age`, {
- rules: [{ required: true, message: "请输入" }],
- initialValue: record["age"],
- })(<Input />)}
- </Form.Item>
- ),
- },
- {
- title: "address",
- dataIndex: "address",
- width: "40%",
- render: (text, record, index) => (
- <Form.Item>
- {getFieldDecorator(`data.${index}.address`, {
- rules: [
- {
- required: true,
- message: "请输入!",
- },
- ],
- initialValue: record["address"],
- })(<Input />)}
- </Form.Item>
- ),
- },
- { title: "operation", dataIndex: "operation" },
- ]; return ( [table][/table] Submit reset );};const WrappedMyFormComponent = Form.create()(App);export default WrappedMyFormComponent;
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |