使用 antd 的 form 元件來自定義提交的資料格式

阿政想暴富發表於2021-09-02

最近使用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函式來自定義校驗規則。

自定義內容提交結果

相關文章