最近使用antd UI 的表單提交資料,資料裡面有的是陣列,有的是物件。提交的時候還要去校驗引數,讓人非常頭疼。在我仔細看完文件之後,發現 antd 的 form 元件做的非常不錯,這些需求通通不是問題。現在來總結一下。
- 如圖所示,提交的表單資訊 有需要填寫多個的東西。資料型別為:陣列(Array)
那麼陣列格式怎麼用 form 元件來渲染呢?
Form.List
- 現在我們來自定義一個表單屬性為一個陣列的表單資料。
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
,提交的資料為陣列格式。如圖
自定義表單元件,在 Form.Item 元件下使用。
Form.Item
子節點的props
接收兩個引數:value
,onChange
。
props | 型別 | 描述 |
---|---|---|
value | any | 表單對應的Form.Item 上name 的值。 |
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
函式來自定義校驗規則。