Form
form表单容器 · Base UI 结构化提交 + errors 按 name + 与 Field 协同
用法
基础用法
Base UI Form 容器,提交时拿到结构化 values(已 preventDefault)。
tsx
<Form className="w-72" onFormSubmit={(v) => console.log(v)}>
<Field label="邮箱" name="email">
<Input name="email" type="email" placeholder="you@example.com" required />
</Field>
<Field label="用户名" name="username">
<Input name="username" placeholder="瑚琏用户" required />
</Field>
<Button type="submit" size="sm">提交</Button>
</Form>服务端错误
errors 按 Field name 映射,把外部/服务端校验结果回显到对应字段。
tsx
<Form
className="w-72"
errors={{ email: "该邮箱已被注册" }}
onFormSubmit={(v) => console.log(v)}
>
<Field label="邮箱" name="email">
<Input name="email" type="email" defaultValue="taken@example.com" />
</Field>
<Button type="submit" size="sm">提交</Button>
</Form>校验规则 + 字段联动(useForm)
useForm 控制器:register 声明规则,dependencies 做字段联动,submit 包裹提交。
tsx
const form = useForm({ initialValues: { email: "", pwd: "", confirm: "" } });
const email = form.register("email", {
rules: [
{ required: true, message: "请填邮箱" },
{ pattern: /^[^@]+@[^@]+$/, message: "邮箱格式不正确" },
],
});
const pwd = form.register("pwd", { rules: [{ required: true, min: 6, message: "至少 6 位" }] });
const confirm = form.register("confirm", {
dependencies: ["pwd"],
rules: [{ validator: (v, values) => { if (v !== values.pwd) throw new Error("两次密码不一致"); } }],
});
<form onSubmit={form.submit(onFinish, onFinishFailed)} noValidate>
<Field label="邮箱" error={email.error}>
<Input value={email.value} onChange={email.onChange} onBlur={email.onBlur} />
</Field>
<Field label="密码" error={pwd.error}>
<Input type="password" value={pwd.value} onChange={pwd.onChange} onBlur={pwd.onBlur} />
</Field>
<Field label="确认密码" error={confirm.error}>
<Input type="password" value={confirm.value} onChange={confirm.onChange} onBlur={confirm.onBlur} />
</Field>
<Button type="submit" size="sm">提交</Button>
</form>动态列表(FormList)
FormList 管理可增删、可移动的重复字段行。
tsx
<FormList<{ name: string }> value={rows} onChange={setRows}>
{(fields, ops, value) => (
<>
{fields.map((f) => (
<div key={f.key} className="flex items-center gap-2">
<Input value={value[f.name]?.name ?? ""} onChange={...} />
<Button onClick={() => ops.remove(f.name)}>删除</Button>
</div>
))}
<Button onClick={() => ops.add({ name: "" })}>+ 添加联系人</Button>
</>
)}
</FormList>何时用
页面内布置一组字段、自己管提交与校验时用。Form 是结构化提交容器(按原生 name 收集 values);useForm 是更强的校验/联动控制器(规则引擎 + 字段依赖 + register/submit);FormList 管动态增删行。需要弹窗/抽屉里提交用 ModalForm / DrawerForm;要自带 footer + 栅格的内联表单用 ProForm;纯查询条件用 SearchForm。
导入
ts
import { Form, useForm, validateValue, FormList } from "@hulianui/ui"Props
Form:
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| validationMode | "onSubmit" | "onBlur" | "onChange" | "onSubmit" | 校验时机 |
| errors | Record<string, string | string[]> | — | 外部/服务端校验错误,按 <Field name> 映射(展示需 Field 内有 Field.Error) |
| className | string | — | 容器类名 |
Events
| 事件 | 类型 | 说明 |
|---|---|---|
| onFormSubmit | (formValues: Record<string, unknown>) => void | 提交时拿到结构化 values(已 preventDefault 原生提交) |
Slots
| 插槽 | 类型 | 说明 |
|---|---|---|
| children | ReactNode | 字段内容 |
useForm 控制器用法(详见示例):form.register(name, { rules, dependencies })、form.submit(onValid, onInvalid)、form.resetFields()。
禁忌 / 坑
validator报错靠throw new Error("...")抛出,不是 return false;联动字段记得在dependencies里声明被依赖字段,否则不会重算。errors(外部/服务端错误)要显示出来,对应Field内必须有Field.Error,且 key 与<Field name>严格对齐。- 用
useForm时给原生<form>加noValidate,避免浏览器原生校验抢在规则引擎前弹气泡。
相关
ModalForm / DrawerForm · ProForm · StepsForm · LoginForm · Field · SearchForm