Form
Formは、複数のフォーム要素をグループ化するためのコンポーネントです。
interface Data {
email: string
name: string
password: string
}
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Header>
<Form.Title>Create an account</Form.Title>
<Form.Description>Create an account to get started.</Form.Description>
</Form.Header>
<Form.Body>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Body>
<Form.Footer>
<Form.SubmitButton>Submit</Form.SubmitButton>
</Form.Footer>
</Form.Root>
)
使い方
import { Form } from "@yamada-ui/react"
import { Form } from "@/components/ui"
import { Form } from "@workspaces/ui"
<Form.Root>
<Form.Header>
<Form.Title />
<Form.Description />
</Form.Header>
<Form.Body>
<Form.Group />
</Form.Body>
<Form.Footer>
<Form.SubmitButton />
</Form.Footer>
</Form.Root>
propsを使う
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
バリアントを変更する
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<VStack>
<For each={["plain", "elevated", "outline", "panel"]}>
{(variant, key) => (
<Form.Root
key={key}
variant={variant}
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Fieldset.Root legend="Personal information">
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Fieldset.Root>
</Form.Root>
)}
</For>
</VStack>
)
サイズを変更する
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<VStack>
<For each={["sm", "md", "lg"]}>
{(size, key) => (
<Form.Root
key={key}
size={size}
variant="panel"
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Fieldset.Root legend="Personal information">
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Fieldset.Root>
</Form.Root>
)}
</For>
</VStack>
)
ヘルプメッセージを表示する
ヘルプメッセージを表示する場合は、helperMessageに{[key: string]: ReactNode}を設定します。
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
エラーメッセージを表示する
エラーメッセージを表示する場合は、errorMessageに{[key: string]: ReactNode}を設定します。
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
必須にする
必須にする場合は、requiredに{[key: string]: boolean}を設定します。
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
無効にする
無効にする場合は、disabledに{[key: string]: boolean}を設定します。
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
disabled={{ password: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
読み取り専用にする
読み取り専用にする場合は、readOnlyに{[key: string]: boolean}を設定します。
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
description="Create an account to get started."
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
readOnly={{ password: true }}
submitButton="Submit"
title="Create an account"
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
必須インジケーターをカスタマイズする
必須インジケーターをカスタマイズする場合は、requiredIndicatorにReactNodeを設定します。
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
requiredIndicator={
<Tag colorScheme="red" size="sm">
required
</Tag>
}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
オプショナルインジケーターを使う
オプショナルインジケーターを使う場合は、optionalIndicatorにReactNodeを設定します。
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
requiredIndicator={
<Tag colorScheme="red" size="sm">
required
</Tag>
}
optionalIndicator={
<Tag colorScheme="mono" size="sm">
optional
</Tag>
}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Props
類似のコンポーネント
Field
Fieldは、フォーム要素に、ラベル、ヘルパーメッセージ、エラーメッセージなどをグループ化するために使用されるコンポーネントです。
Fieldset
Fieldsetは、フィールドセット要素に、レジェンド、ヘルパーメッセージ、エラーメッセージなどをグループ化するために使用されるコンポーネントです。
ZStack
ZStackは、子要素を奥行き方向にスタックするために使用されます。
VStack
VStackは、子要素を垂直方向にスタックするために使用されます。
Wrap
Wrapは、Flexにwrapを設定したコンポーネントです。Flexから便利なスタイルのショートハンドを継承しています。
Stack
Stackは、要素をグループ化し、子要素間にスペースを設けるコンポーネントです。
Spacer
Spacerは、要素間に空間を追加するために使用するコンポーネントです。
SimpleGrid
SimpleGridは、Gridをより使いやすくシンプルにしたコンポーネントです。
使用しているコンポーネント・フック
Fieldset
Fieldsetは、フィールドセット要素に、レジェンド、ヘルパーメッセージ、エラーメッセージなどをグループ化するために使用されるコンポーネントです。
Button
Buttonは、フォームの送信、モーダルの開閉など、ユーザーが操作できるインタラクティブなコンポーネントです。