使用 antd 的 form 组件来自定义提交的数据格式

时间:2024-02-17 17:51:07

最近使用antd UI 的表单提交数据,数据里面有的是数组,有的是对象。提交的时候还要去校验参数,让人非常头疼。在我仔细看完文档之后,发现 antd 的 form 组件做的非常不错,这些需求通通不是问题。现在来总结一下。

  • 如图所示,提交的表单信息 有需要填写多个的东西。数据类型为:数组(Array)
    示例

那么数组格式怎么用 form 组件来渲染呢?

Form.List

antd formlist 文档

  • 现在我们来自定义一个表单属性为一个数组的表单数据。
import { useState } from "react";
import { Button, Col, Form, Input, Row } from "antd";
import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";

function validator(_, val) {
  if (!val) {
    return Promise.reject(new Error("添加的价格为必填项!"));
  }
  if (!/^\d+$/.test(val) || val <= 0) {
    return Promise.reject(new Error("价格必须为数字且大于0"));
  }
  return Promise.resolve();
}
function validators(_, vals) {
  console.log(vals);
  if (!vals || vals.length === 0) {
    return Promise.reject("请填写价格!");
  }
  return Promise.resolve();
}
export default function MyForm() {
  const [formInstance] = Form.useForm();
  const submit = () => {
    // 点击 验证表单信息
    formInstance.validateFields().then((vals) => {
      console.log(vals);
    });
  };
  return (
    <Form form={formInstance} labelCol={{ span: 2 }} wrapperCol={{ span: 6 }}>
      <Form.List name="price" rules={[{ validator: validators }]}>
        {(fields, { add, remove }, { errors }) => (
          <div>
            {fields.map((field) => {
              return (
                <Form.Item
                  {...field}
                  key={field.name}
                  rules={[{ validator: validator }]}
                  validateTrigger={["onChange", "onBlur"]}
                >
                  <Input
                    suffix={
                      <MinusCircleOutlined onClick={() => remove(field.name)} />
                    }
                  />
                </Form.Item>
              );
            })}
            <Row style={{ marginBottom: 20 }}>
              <Button
                type="dashed"
                {/* 点击添加列 */}
                onClick={() => {
                  add();
                }}
                icon={<PlusOutlined />}
              >
                添加价格
              </Button>
            </Row>
            {/* formList 的 验证报错信息 */}
            <Form.ErrorList errors={errors} />
          </div>
        )}
      </Form.List>
      <Row>
        <Button type="primary" onClick={submit}>
          submit
        </Button>
      </Row>
    </Form>
  );
}
  • 点击表单提交的时候会验证 Form.List 和 子节点的 Form.Item 。前提是节点上有rules,提交的数据为数组格式。如图

formList提交信息

自定义表单组件,在 Form.Item 组件下使用。

Form.Item子节点的props接收两个参数:value,onChange

props 类型 描述
value any 表单对应的Form.Itemname的值。
onChange function 修改表单属性值。
// 因为 定义的 value 是 包含 fisrt,last属性所以使用Object类型。默认空对象
function Name({ value = {}, onChange }) {
  const [first, setFirst] = useState(null);
  const [last, setLast] = useState(null);
  // 值改变就调用 onChange 因为使用的是对象所以调用的时候传对象。
  const triggerChange = (checkVal) => {
    onChange &&
      onChange({
        first: first,
        last: last,
        ...value,
        ...checkVal,
      });
  };
  const firstChange = (e) => {
    const val = e.target.value;
    setFirst(val);
    triggerChange({ first: val });
  };
  const lastChange = (e) => {
    const val = e.target.value;
    setLast(val);
    triggerChange({ last: val });
  };
  return (
    <Row justify="center">
      <Col span={12}>
        <Input
          placeholder="first name"
          value={value.first || first}
          onChange={firstChange}
        />
      </Col>
      <Col span={12}>
        <Input
          placeholder="last name"
          value={value.last || last}
          onChange={lastChange}
        />
      </Col>
    </Row>
  );
}
// 在上面的 MyForm组件上追加一点内容
function MyForm() {
  // .... 此内容不变
  return (
    <Form form={formInstance} labelCol={{ span: 2 }} wrapperCol={{ span: 6 }}>
      {/* .... ...   忽略上面的 Form.List*/}
      <Form.Item name="username" label="username">
        <Name />
      </Form.Item>
      <Row>
        <Button type="primary" onClick={submit}>
          submit
        </Button>
      </Row>
    </Form>
  );
}
  • 若需要使用表单验证自定义组件的值,在Form.Item上添加rules,使用validator函数来自定义校验规则。

自定义内容提交结果