antd中Form深层绑定,Form.List+Table

Form.List 利用Form.Item的name来深层绑定

name为索引数组,[index,name] : [数据的第几个(从0开始),数据绑定参数名]

合起来代表的含义: map[index].name

name绑定正确才能触发form的校验和绑定

最简单的使用:

只使用FornList

下述代码可以生成一个可增删的列表

fields为jonData数组处理后的数据,fileld.name即数据绑定的index,form根据该数据来进行增删

      <Form
        ref={formvalue}
        form={form}
        autoComplete="off"
        initialValues={{
          jonData: [
            {
              building: "22",
              version: "",
            },
          ],
        }}
      >
        <Form.List name="jonData">
          {(fields, { add, remove }) => (
            <div
              style={{
                display: "flex",
                rowGap: 16,
                flexDirection: "column",
              }}
            >
              {fields.map((field) => (
                <Card
                  size="small"
                  title={`Item ${field.name + 1}`}
                  key={field.key}
                  extra={
                    <CloseOutlined
                      onClick={() => {
                        remove(field.name);
                      }}
                    />
                  }
                >
                  <Form.Item label="building" name={[field.name, "building"]}>
                    <Input />
                  </Form.Item>
                  <Form.Item label="version" name={[field.name, "version"]}>
                    <Input />
                  </Form.Item>
                </Card>
              ))}

              <Button type="dashed" onClick={() => add()} block>
                + Add Item
              </Button>
            </div>
          )}
        </Form.List>
      </Form>

 深层嵌套:

在Form中本身支持嵌套模式,其实现也同样依赖于name数组

下述代码用 name={[field.name, "doorButton", "frontOpen"]}绑定了jonData中每一项的doorButton.frontOpen

  <Form
        ref={formvalue}
        form={form}
        autoComplete="off"
        initialValues={{
          jonData: [
            {
              building: "22",
              version: "0101",
              doorButton: {
                frontOpen: 0,
                backOpen: 1,
              },
            },
          ],
        }}
      >
        <Form.List name="jonData">
          {(fields, { add, remove }) => (
            <div
              style={{
                display: "flex",
                rowGap: 16,
                flexDirection: "column",
              }}
            >
              {fields.map((field) => (
                <Card
                  size="small"
                  title={`Item ${field.name + 1}`}
                  key={field.key}
                  extra={
                    <CloseOutlined
                      onClick={() => {
                        remove(field.name);
                      }}
                    />
                  }
                >
                  <Form.Item label="楼栋" name={[field.name, "building"]}>
                    <Input />
                  </Form.Item>
                  <Form.Item label="version" name={[field.name, "version"]}>
                    <Input />
                  </Form.Item>
                  <Form.Item
                    label='深层绑定'
                    name={[field.name, "doorButton", "frontOpen"]}
                  >
                    <InputNumber min={0} placeholder={translate["请输入"]} />
                  </Form.Item>
                </Card>
              ))}

              <Button type="dashed" onClick={() => add()} block>
                + Add Item
              </Button>
            </div>
          )}
        </Form.List>
      </Form>

 动态数据更新

如果需要某一部分随着表单中的某一项的值改变而改变,form提供了shouldUpdate

prevValues为之前的值, currentValues为改变之后的值,同样使用name绑定的层级来获取

 getFieldValue([*,*,*])可以获取某个字段的值-实时变化-用以shouldUpdate更新,必须用该函数包裹dom才会更新

<Form.Item
   // 楼栋信息变化--此组件包裹的内容将调用更新
   shouldUpdate={(prevValues, currentValues) =>
      prevValues.jonData[field.name]?.building !==
      currentValues.jonData[field.name]?.building
     }
 >
   {/* getFieldValue([*,*,*])可以获取某个字段的值-实时变化-用以shouldUpdate更新 */}
    {({ getFieldValue }) =>
          getFieldValue(["jonData", field.name, "building"]) !=="building" ? (
             <>
                 <Form.Item label="key" name={[field.name, "key"]}>
                     <Input />
                 </Form.Item>
                  <Form.Item
                   label="deviceId"
                    name={[field.name, "deviceId"]}
                  >
                     <Input />
                  </Form.Item>
              </>
             ) : null
                    }
</Form.Item>

多层Form.List 

我们可以在list中嵌套list,正如上述的fields遍历一样,form.item绑定了name,即可在该层级上拿到绑定数据,用绑定数据来遍历

示例:

下方代码,floorMap即二层绑定

 <Form
        ref={formvalue}
        form={form}
        autoComplete="off"
        initialValues={{
         jonData: [
        {
          building: "22",
          version: "0101",
          doorButton: {
            frontOpen: 0,
            backOpen: 1, 
          },
          floorMap: [
            {
              floor: 1,
            },
          ],
        },
      ],
        }}
      >
        <Form.List name="jonData">
          {(fields, { add, remove }) => (
            <div
              style={{
                display: "flex",
                rowGap: 16,
                flexDirection: "column",
              }}
            >
              {fields.map((field) => (
                <Card
                  size="small"
                  title={`Item ${field.name + 1}`}
                  key={field.key}
                  extra={
                    <CloseOutlined
                      onClick={() => {
                        remove(field.name);
                      }}
                    />
                  }
                >
                  <Form.Item label="楼building" name={[field.name, "building"]}>
                    <Input />
                  </Form.Item>
                  <Form.Item label="version" name={[field.name, "version"]}>
                    <Input />
                  </Form.Item>
                  <Form.Item label="floorMap">
                    <Form.List name={[field.name, "floorMap"]}>
                      {(subFields, subOpt) => (
                        <>
                          {subFields.map((subField) => (
                            <Space key={subField.key}>
                              <Form.Item
                                noStyle
                                name={[subField.name, "floor"]}
                              >
                                <Input placeholder="floor" />
                              </Form.Item>
                              <CloseOutlined
                                onClick={() => {
                                  subOpt.remove(subField.name);
                                }}
                              />
                            </Space>
                          ))}
                          <Button
                            type="dashed"
                            onClick={() => subOpt.add()}
                            block
                          >
                            + Add Sub Item
                          </Button>
                        </>
                      )}
                    </Form.List>
                  </Form.Item>
                </Card>
              ))}

              <Button type="dashed" onClick={() => add()} block>
                + Add Item
              </Button>
            </div>
          )}
        </Form.List>
      </Form>

双层可编辑表格绑定 

将表格中的可编辑的表单与form绑定,直接利用form的表单绑定与校验,可节省很多开发时间

用antd的table ,将tr td单拆出来,name绑定原理也是当层[index,参数名]

table的表格数据绑定即本层的floorMap----subFields

实例:

完整代码: 

import React, { useContext, useEffect, useRef, useState } from "react";
import { Button, Form, Input, Card, Table, Space } from "antd";
import { CloseOutlined } from "@ant-design/icons";
import "./index.scss";

const ExitTable = () => {
  const [form] = Form.useForm();
  const formvalue = useRef(null);
  const handleSubmit = () => {
    console.log(222222, form.getFieldsValue());
  };
  //表格配置
  const defaultColumns = [
    {
      title: "floor",
      dataIndex: "floor",
      width: "30%",
      editable: true,
    },
    {
      title: "floorName",
      dataIndex: "floorName",
      editable: true,
    },
    {
      title: "删除",
      dataIndex: "delete",
      editable: true,
    },
  ];
  const columns = defaultColumns.map((col, index) => {
    if (!col.editable) {
      return col;
    }
    return {
      ...col,
      onCell: (record) => ({
        record,
        col: col,
        editable: col.editable,
        dataIndex: col.dataIndex,
        title: col.title,
      }),
    };
  });

  useEffect(() => {
    form.setFieldsValue({
      jonData: [
        {
          liftId: 1,
          type: "",
          building: "22",
          version: "0101",
          key: "xsxsx",
          deviceId: "xsx",
          doorButton: {
            frontOpen: 0,
            backOpen: 1, 
          },
          floorMap: [
            {
              floor: 1,
            },
          ],
        },
      ],
    });
  }, []);
  return (
    <div>
      <Form
        ref={formvalue}
        labelCol={{
          span: 5,
        }}
        wrapperCol={{
          span: 18,
        }}
        form={form}
        name="dynamic_form_complex"
        style={{
          maxWidth: 700,
        }}
        autoComplete="off"
        initialValues={{
          jonData: [],
        }}
      >
        <Form.List name="jonData">
          {(fields, { add, remove }) => (
            <div
              style={{
                display: "flex",
                rowGap: 16,
                flexDirection: "column",
              }}
            >
              {fields.map((field) => (
                <Card
                  size="small"
                  title={`Item ${field.name + 1}`}
                  key={field.key}
                  extra={
                    <CloseOutlined
                      onClick={() => {
                        remove(field.name);
                      }}
                    />
                  }
                >
                  <Form.Item label="building" name={[field.name, "building"]}>
                    <Input />
                  </Form.Item>
                  <Form.Item label="version" name={[field.name, "version"]}>
                    <Input />
                  </Form.Item>
                  <Form.Item label="floorMap">
                    <Form.List name={[field.name, "floorMap"]}>
                      {(subFields, subOpt) => (
                        <>
                          <Button
                            onClick={() => {
                              subOpt.add();
                            }}
                          >
                            新增
                          </Button>
                          <Table
                            components={{
                              body: {
                                cell: ({
                                  title,
                                  editable,
                                  children,
                                  dataIndex,
                                  record,
                                  col,
                                  ...restProps
                                }) => {
                                  return (
                                    <td {...restProps}>
                                      {record && dataIndex == "delete" ? (
                                        <Button
                                          onClick={() => {
                                            subOpt.remove(record.name);
                                          }}
                                        >
                                          删除
                                        </Button>
                                      ) : (
                                        record && (
                                          <Form.Item
                                            style={{
                                              margin: 0,
                                            }}
                                            name={[record.name, dataIndex]}
                                            // rules={[
                                            //   {
                                            //     required: true,
                                            //     message: `${title} is required.`,
                                            //   },
                                            // ]}
                                          >
                                            <Input />
                                          </Form.Item>
                                        )
                                      )}
                                    </td>
                                  );
                                },
                              },
                            }}
                            rowClassName={() => "editable-row"}
                            bordered
                            dataSource={subFields}
                            columns={columns}
                            rowKey="key"
                            pagination={false}
                          />
                        </>
                      )}
                    </Form.List>
                  </Form.Item>
                </Card>
              ))}

              <Button type="dashed" onClick={() => add()} block>
                + Add Item
              </Button>
            </div>
          )}
        </Form.List>
      </Form>

      <Button onClick={handleSubmit}>提交</Button>
    </div>
  );
};
export default ExitTable;

一些常用函数 

1.设置表单值()

设置表单值--总体设置setFieldsValue

form.setFieldsValue({

      jonData: [

        {

          building: "22",

          version: "0101",

          doorButton: {

            frontOpen: 0,

            backOpen: 1,

          },

        },

      ],

    });

 设置指定位置的值 --单个设置  setFieldValue

 form.setFieldValue(

                                      [

                                        "jonData",

                                        field.name,

                                        "floorMap",

                                        subField.name,

                                        "floorKey",

                                      ],

                                     '新值'

                                    );

                                  }}

2.获取表单值

获取全部表单的值getFieldsValue

form.getFieldsValue()

获取指定位置的值 getFieldValue

  form.getFieldValue([

                                          "jonData",

                                          field.name,

                                          "building",

           ])

3.触发表单校验validateFields

  form.validateFields().then(()=>{}).catch(()=>{})

表单校验失败滚动到初始位置

  form.validateFields().then(()=>{}).catch((error)=>{

form.scrollToField(error.errorFields[0].name) 

})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值