Components

表单

使用验证规则收集用户信息。

import * as React from "react";
import { Form } from "radix-ui";
import "./styles.css";
const FormDemo = () => (
<Form.Root className="FormRoot">
<Form.Field className="FormField" name="email">
<div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", }} >
<Form.Label className="FormLabel">Email</Form.Label>
<Form.Message className="FormMessage" match="valueMissing">
Please enter your email
</Form.Message>
<Form.Message className="FormMessage" match="typeMismatch">
Please provide a valid email
</Form.Message>
</div>
<Form.Control asChild>
<input className="Input" type="email" required />
</Form.Control>
</Form.Field>
<Form.Field className="FormField" name="question">
<div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", }} >
<Form.Label className="FormLabel">Question</Form.Label>
<Form.Message className="FormMessage" match="valueMissing">
Please enter a question
</Form.Message>
</div>
<Form.Control asChild>
<textarea className="Textarea" required />
</Form.Control>
</Form.Field>
<Form.Submit asChild>
<button className="Button" style={{ marginTop: 10 }}>
Post question
</button>
</Form.Submit>
</Form.Root>
);
export default FormDemo;

Features

    基于原生浏览器 约束验证 API。

    支持内置验证。

    支持自定义验证。

    完全自定义验证消息。

    可访问的验证消息。

    支持客户端和服务器端场景。

    焦点完全管理。

安装

从命令行安装组件。

npm install @radix-ui/react-form

解剖

导入所有部分并将它们组合在一起。

import { Form } from "radix-ui";
export default () => (
<Form.Root>
<Form.Field>
<Form.Label />
<Form.Control />
<Form.Message />
<Form.ValidityState />
</Form.Field>
<Form.Message />
<Form.ValidityState />
<Form.Submit />
</Form.Root>
);

API 参考

Root

包含表单的所有部分。

PropTypeDefault
asChild
boolean
false
onClearServerErrors
function
No default value

Field

字段的包装器。它自动处理 ID/名称和标签的可访问性。

PropTypeDefault
asChild
boolean
false
name*
string
No default value
serverInvalid
boolean
No default value
Data attributeValues
[data-invalid]

字段无效时存在

[data-valid]

字段有效时存在

Label

一个标签元素,当嵌套在 Field 部分内时会自动连接。

PropTypeDefault
asChild
boolean
false
Data attributeValues
[data-invalid]

字段无效时存在

[data-valid]

字段有效时存在

Control

一个控制元素(默认是 input),当嵌套在 Field 部分内时会自动连接。

PropTypeDefault
asChild
boolean
false
Data attributeValues
[data-invalid]

字段无效时存在

[data-valid]

字段有效时存在

Message

当嵌套在 Field 部分内时,验证消息会自动连接(功能和可访问性)到给定的控件。它可用于内置和自定义客户端验证,以及服务器端验证。当在 Field 外部使用时,必须传递一个与字段相匹配的 name 属性。

Form.Message 接受一个 match 属性,用于确定何时应显示该消息。它匹配原生 HTML 有效性状态(ValidityStateMDN 上),该状态会验证 requiredminmax 等属性。如果控件的有效性状态中的给定 matchtrue,则消息将显示。

您还可以将函数传递给 match 以提供自定义验证规则。

PropTypeDefault
asChild
boolean
false
match
Matcher
No default value
forceMatch
boolean
false
name
string
No default value

ValidityState

使用此渲染属性组件访问给定字段的有效性状态(请参见 MDN 上的 ValidityState)。在嵌套在 Field 部分内时,字段的有效性会自动可用,否则必须传递一个 name 属性以关联它。

PropTypeDefault
children
function
No default value
name
string
No default value

Submit

提交按钮。

PropTypeDefault
asChild
boolean
false

示例

与您自己的组件组合

使用 asChild,您可以将 Form 原语部分与您自己的组件组合。

<Form.Field name="name">
<Form.Label>全名</Form.Label>
<Form.Control asChild>
<TextField.Input variant="primary" />
</Form.Control>
</Form.Field>

它也可以用于组合其他类型的控件,例如 select

<Form.Field name="country">
<Form.Label>国家</Form.Label>
<Form.Control asChild>
<select>
<option value="uk">英国</option>
</select>
</Form.Control>
</Form.Field>

注意: 目前还不可能将 Form 与 Radix 的其他表单原语如 CheckboxSelect 等组合。我们正在寻找解决方案。

提供您自己的验证消息

当未提供 children 时,Form.Message 将为给定的 match 渲染默认错误消息。

// 将产生 "此值缺失"
<Form.Message match="valueMissing" />

通过传递您自己的 children,可以提供更有意义的消息。这对于国际化也很有用。

// 将产生 "请提供一个名称"
<Form.Message match="valueMissing">请提供一个名称</Form.Message>

自定义验证

除了上述所有内置的客户端验证匹配之外,您还可以在仍然利用平台验证能力的同时提供自己的自定义验证。它使用 约束验证 API 中的 customError 类型。

可以将您自己的验证函数传递到 Form.Message 上的 match 属性。以下是一个示例:

<Form.Field name="name">
<Form.Label>全名</Form.Label>
<Form.Control />
<Form.Message match={(value, formData) => value !== "John"}>
只有约翰被允许。
</Form.Message>
</Form.Field>

match 将以控件的当前值作为第一个参数,整个 FormData 作为第二个参数调用。 match 也可以是一个 async 函数(或返回一个 promise)以执行异步验证。

基于有效性进行样式设置

我们向相关部分添加了 data-validdata-invalid 属性。利用它相应地设置您的组件样式。以下是样式设置 Label 部分的示例。

//index.jsx
import * as React from "react";
import { Form } from "radix-ui";
export default () => (
<Form.Root>
<Form.Field name="email">
<Form.Label className="FormLabel">电子邮件</Form.Label>
<Form.Control type="email" />
</Form.Field>
</Form.Root>
);
/* styles.css */
.FormLabel[data-invalid] {
color: red;
}
.FormLabel[data-valid] {
color: green;
}

访问有效性状态以获得更多控制

您可能需要访问字段的原始有效性状态,以显示自己定义的图标,或通过其定义的属性与组件库进行交互。您可以通过使用 Form.ValidityState 部分来做到这一点:

<Form.Field name="name">
<Form.Label>全名</Form.Label>
<Form.ValidityState>
{(validity) => (
<Form.Control asChild>
<TextField.Input variant="primary" state={getTextFieldInputState(validity)} />
</Form.Control>
)}
</Form.ValidityState>
</Form.Field>

服务器端验证

该组件还支持使用相同的 Form.Message 组件进行服务器端验证。 您可以通过传递 forceMatch 属性来重用为客户端错误定义的相同消息,无论客户端匹配逻辑如何,均强制显示该消息。

如果客户端上不存在该消息,您也可以渲染没有 matchForm.Message。 通过将 serverInvalid 布尔属性传递给 Form.Field 部分,可以将字段标记为无效。

以下是带有服务器端错误处理的示例:

import * as React from "react";
import { Form } from "radix-ui";
function Page() {
const [serverErrors, setServerErrors] = React.useState({
email: false,
password: false,
});
return (
<Form.Root // `onSubmit` 仅在通过客户端验证时触发 onSubmit={(event) => { const data = Object.fromEntries(new FormData(event.currentTarget)); // 提交表单数据并捕获响应中的错误 submitForm(data) .then(() => {}) /** * 将服务器响应中的错误映射到您喜欢的结构。 * 在这种情况下 resulting in this object: `{ email: false, password: true }` */ .catch((errors) => setServerErrors(mapServerErrors(errors))); // 防止默认表单提交 event.preventDefault(); }} onClearServerErrors={() => setServerErrors({ email: false, password: false }) } >
<Form.Field name="email" serverInvalid={serverErrors.email}>
<Form.Label>电子邮件地址</Form.Label>
<Form.Control type="email" required />
<Form.Message match="valueMissing">
请输入您的电子邮件。
</Form.Message>
<Form.Message match="typeMismatch" forceMatch={serverErrors.email}>
请输入有效的电子邮件。
</Form.Message>
</Form.Field>
<Form.Field name="password" serverInvalid={serverErrors.password}>
<Form.Label>密码</Form.Label>
<Form.Control type="password" required />
<Form.Message match="valueMissing">
请输入密码。
</Form.Message>
{serverErrors.password && (
<Form.Message>
请提供有效的密码。它应包含至少 1 个数字和 1 个特殊字符。
</Form.Message>
)}
</Form.Field>
<Form.Submit>提交</Form.Submit>
</Form.Root>
);
}

您应该使用 Form.Root 部分的 onClearServerErrors 回调属性清除服务器错误。在表单重新提交之前和表单重置时,它将清除服务器错误。

此外,这还提供了何时重置单个服务器错误的控制。例如,您可以在用户编辑它时立即重置电子邮件服务器错误:

<Form.Field name="email" serverInvalid={serverErrors.email}>
<Form.Label>电子邮件地址</Form.Label>
<Form.Control type="email" onChange={() => setServerErrors((prev) => ({ ...prev, email: false }))} />
<Form.Message match="valueMissing">请输入您的电子邮件。</Form.Message>
<Form.Message match="typeMismatch" forceMatch={serverErrors.email}>
请输入有效的电子邮件。
</Form.Message>
</Form.Field>

可访问性

该组件遵循“内联错误”模式进行验证:

  • 使用 Form.Field 中提供的 name 将标签和控件关联
  • 当一个或多个客户端错误消息显示时,它们会自动与其匹配控件关联,并相应地宣布
  • 焦点移到第一个无效控件