Components

表单

¥Form

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

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

    Built on top of the native browser constraint validation API.

    Supports built-in validation.

    Supports custom validation.

    Full customization of validation messages.

    Accessible validation messages.

    Supports client-side and server-side scenarios.

    Focus is fully managed.

安装

¥Installation

从命令行安装组件。

¥Install the component from your command line.

npm install @radix-ui/react-form

结构

¥Anatomy

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

¥Import all parts and piece them together.

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 参考

¥API Reference

¥Root

包含表单的所有部分。

¥Contains all the parts of a form.

PropTypeDefault
asChild
boolean
false
onClearServerErrors
function
No default value

字段

¥Field

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

¥The wrapper for a field. It handles id/name and label accessibility automatically.

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

Present when the field is invalid

[data-valid]

Present when the field is valid

标签

¥Label

嵌套在 Field 部件中时会自动连接的标签元素。

¥A label element which is automatically wired when nested inside a Field part.

PropTypeDefault
asChild
boolean
false
Data attributeValues
[data-invalid]

Present when the field is invalid

[data-valid]

Present when the field is valid

控件

¥Control

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

¥A control element (by default an input) which is automatically wired when nested inside a Field part.

PropTypeDefault
asChild
boolean
false
Data attributeValues
[data-invalid]

Present when the field is invalid

[data-valid]

Present when the field is valid

消息

¥Message

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

¥A validation message which is automatically wired (functionality and accessibility) to a given control when nested inside a Field part. It can be used for built-in and custom client-side validation, as well as server-side validation. When used outside a Field you must pass a name prop matching a field.

Form.Message 接受 match 属性,用于确定消息何时显示。它与原生 HTML 有效性状态(ValidityState on MDN)匹配,该状态会根据 requiredminmax 等属性进行验证。如果在控件的有效性状态下,给定的 matchtrue,则会显示该消息。

¥Form.Message accepts a match prop which is used to determine when the message should show. It matches the native HTML validity state (ValidityState on MDN) which validates against attributes such as required, min, max. The message will show if the given match is true on the control’s validity state.

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

¥You can also pass a function to match to provide custom validation rules.

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

ValidityState

使用此 render-prop 组件在渲染过程中访问给定字段的有效性状态(请参阅 MDN 上的 ValidityState)。当字段嵌套在 Field 部件中时,其有效性会自动生效,否则必须传递 name 属性来关联它。

¥Use this render-prop component to access a given field’s validity state in render (see ValidityState on MDN). A field's validity is available automatically when nested inside a Field part, otherwise you must pass a name prop to associate it.

PropTypeDefault
children
function
No default value
name
string
No default value

提交

¥Submit

提交按钮。

¥The submit button.

PropTypeDefault
asChild
boolean
false

示例

¥Examples

使用你自己的组件

¥Composing with your own components

使用 asChild,你可以使用自己的组件组合 Form 基本部分。

¥Using asChild you can compose the Form primitive parts with your own components.

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

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

¥It can also be used to compose other types of controls, such as a select:

<Form.Field name="country">
<Form.Label>Country</Form.Label>
<Form.Control asChild>
<select>
<option value="uk">United Kingdom</option>
</select>
</Form.Control>
</Form.Field>

注意:目前,无法将 Form 与 Radix 的其他表单基元(例如 CheckboxSelect 等)组合在一起。我们正在研究解决方案。

提供你自己的验证消息

¥Providing your own validation messages

如果未提供 childrenForm.Message 将为给定的 match 呈现默认错误消息。

¥When no children are provided, Form.Message will render a default error message for the given match.

// will yield "This value is missing"
<Form.Message match="valueMissing" />

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

¥You can provide a more meaningful message by passing your own children. This is also useful for internationalization.

// will yield "Please provide a name"
<Form.Message match="valueMissing">Please provide a name</Form.Message>

自定义验证

¥Custom validation

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

¥On top of all the built-in client-side validation matches described above you can also provide your own custom validation whilst still making use of the platform's validation abilities. It uses the customError type present in the constraint validition API.

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

¥You can pass your own validation function into the match prop on Form.Message. Here's an example:

<Form.Field name="name">
<Form.Label>Full name</Form.Label>
<Form.Control />
<Form.Message match={(value, formData) => value !== "John"}>
Only John is allowed.
</Form.Message>
</Form.Field>

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

基于有效性的样式

¥Styling based on validity

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

¥We add data-valid and data-invalid attributes to the relevant parts. Use it to style your components accordingly. Here is an example styling the Label part.

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

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

¥Accessing the validity state for more control

你可能需要访问字段的原始有效性状态,以便显示你自己的图标,或通过其定义的属性与组件库交互。你可以使用 Form.ValidityState 部分执行此操作:

¥You may need to access the raw validity state of a field in order to display your own icons, or interface with a component library via it's defined props. You can do this by using the Form.ValidityState part:

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

服务器端验证

¥Server-side validation

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

¥The component also supports server-side validation using the same Form.Message component. You can re-use the same messages you defined for client-side errors by passing a forceMatch prop which will force the message to show regardless of the client-side matching logic.

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

¥If the message doesn't exist on the client-side, you can render a Form.Message without a match too. The field is marked as invalid by passing a serverInvalid boolean prop to the Form.Field part.

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

¥Here's an example with server-side error handling:

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` only triggered if it passes client-side validation onSubmit={(event) => { const data = Object.fromEntries(new FormData(event.currentTarget)); // Submit form data and catch errors in the response submitForm(data) .then(() => {}) /** * Map errors from your server response into a structure you'd like to work with. * In this case resulting in this object: `{ email: false, password: true }` */ .catch((errors) => setServerErrors(mapServerErrors(errors))); // prevent default form submission event.preventDefault(); }} onClearServerErrors={() => setServerErrors({ email: false, password: false }) } >
<Form.Field name="email" serverInvalid={serverErrors.email}>
<Form.Label>Email address</Form.Label>
<Form.Control type="email" required />
<Form.Message match="valueMissing">
Please enter your email.
</Form.Message>
<Form.Message match="typeMismatch" forceMatch={serverErrors.email}>
Please provide a valid email.
</Form.Message>
</Form.Field>
<Form.Field name="password" serverInvalid={serverErrors.password}>
<Form.Label>Password</Form.Label>
<Form.Control type="password" required />
<Form.Message match="valueMissing">
Please enter a password.
</Form.Message>
{serverErrors.password && (
<Form.Message>
Please provide a valid password. It should contain at least 1 number
and 1 special character.
</Form.Message>
)}
</Form.Field>
<Form.Submit>Submit</Form.Submit>
</Form.Root>
);
}

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

¥You should clear the server errors using the onClearServerErrors callback prop on the Form.Root part. It will clear the server errors before the form is re-submitted, and when the form is reset.

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

¥In addition, this provides control over when to reset single server errors. For example you could reset the email server error as soon as the user edits it:

<Form.Field name="email" serverInvalid={serverErrors.email}>
<Form.Label>Email address</Form.Label>
<Form.Control type="email" onChange={() => setServerErrors((prev) => ({ ...prev, email: false }))} />
<Form.Message match="valueMissing">Please enter your email.</Form.Message>
<Form.Message match="typeMismatch" forceMatch={serverErrors.email}>
Please provide a valid email.
</Form.Message>
</Form.Field>

可访问性

¥Accessibility

该组件遵循 "内联错误" 验证模式:

¥The component follows the "inline errors" pattern for validation:

  • 标签和控件使用 Form.Field 上提供的 name 关联。

    ¥Label and control are associated using the name provided on Form.Field

  • 当显示一个或多个客户端错误消息时,它们会自动与其匹配的控件关联并相应地进行宣告。

    ¥When one or more client-side error messages display, they are automatically associated with their matching control and announced accordingly

  • 焦点已移至第一个无效控件

    ¥Focus is moved to the first invalid control