Yup
Basic usage:
"use client";
import { YupProvider, fieldConfig } from "@acp-autoform/yup";
import { object, string, number, date, InferType, array, mixed } from "yup";
import { AutoForm, FieldTypes } from "@acp-autoform/mui"; // use any UI library
// Define your form schema using yup
const yupFormSchema = object({
name: string().required().label("Your Name").default("John Doe"),
age: number()
.required(
// You can use custom error messages
"We need your age to verify you're old enough to use this form",
)
.positive()
.integer(),
email: string()
.email()
// You can use fieldConfig to set additional configuration for a field
.transform(
fieldConfig<React.ReactNode, FieldTypes, any, { isImportant?: boolean }>({
inputProps: {
type: "email",
},
customData: {
// You can add custom data here
isImportant: true,
},
}),
),
website: string().url().nullable(),
// You can use arrays and sub-objects
guests: array().of(
object({
name: string().required(),
}),
),
hobbies: array().of(string()),
// You can use enums
sport: mixed().oneOf(Object.values(Sports)),
});
export const yupSchemaProvider = new YupProvider(yupFormSchema);
function App() {
return (
<AutoForm
schema={yupSchemaProvider}
onSubmit={(data) => {
console.log(data);
}}
withSubmit
/>
);
}YupProvider exposes the original schema and schema type to @acp-autoform/react, so AutoForm can create a React Hook Form resolver automatically. You do not need to configure a Yup resolver manually when using the official provider.
Yup configuration
Label
You can use the label method to set a label and description for each field. If no label is set, the field name will be used and un-camel-cased.
const formSchema = object({
username: string().label("Your username"),
someValue: string(), // Will be "Some Value"
});To add a description below the field see fieldConfig.
Optional fields
Yup fields are optional by default. Use required() to make a field required.
const formSchema = object({
username: string().required(),
nickname: string(), // Optional by default
});Default values
You can set a default value for a field using the default method.
const formSchema = object({
favouriteNumber: number().default(5),
});.default() acts as a fallback during validation: If a user clears the field,
the default value comes back in the output. If you want pre-filled initial
values that the user can freely clear, then use the
defaultValues prop instead. See
Yup .default().
If you want to set default value of date, convert it to Date first using new Date(val).
Select/Enums
You can use mixed().oneOf to create a select field.
const formSchema = object({
color: mixed().oneOf(["red", "green", "blue"]),
});
enum BreadTypes {
// For TypeScript enums, the enum values (e.g. "White bread")
// are displayed, validated and returned in output.
White = "White bread",
Brown = "Brown bread",
Wholegrain = "Wholegrain bread",
}
const formSchema = object({
breadType: mixed().oneOf(Object.values(BreadTypes)),
});If you want a select label to submit a different value, map the labels to values in a transform.:
const nameId = {
name1: "id1",
name2: "id2",
} as const;
const formSchema = object({
nameId: mixed()
.oneOf(Object.keys(nameId))
.transform((value) => nameId[value as keyof typeof nameId]),
});Arrays
AutoForm supports arrays:
const formSchema = object({
invitedGuests: array(
// Define the fields for each item
object({
name: string(),
age: number(),
}),
)
// Optionally set a custom label - otherwise this will be inferred from the field name
.label("Guests invited to the party"),
hobbies: array(string()),
});Arrays are not supported as the root element of the form schema.
You also can set default value of an array using .default(), but please make sure the array element has same structure with the schema.
const formSchema = object({
invitedGuests: array(
object({
name: string().required(),
age: number(),
}),
)
.default([
{ name: "John", age: 24 },
{ name: "Jane", age: 20 },
])
.label("Guests invited to the party"),
});Sub-objects
You may use sub-objects to group fields together. These will be rendered with their own title.
const formSchema = object({
guestDetails: object({
name: string(),
age: number(),
}),
});Field configuration
Use the fieldConfig function to customize how a field is rendered. Import it from @acp-autoform/yup.
With Yup, attach it to a field using .transform(fieldConfig(...)):
import { fieldConfig } from "@acp-autoform/yup";
import { object, string } from "yup";
const formSchema = object({
username: string()
.required()
.transform(
fieldConfig({
label: "Username",
description: "Choose a unique username.",
inputProps: {
placeholder: "Enter your username",
},
}),
),
password: string()
.required()
.transform(
fieldConfig({
inputProps: {
type: "password",
placeholder: "Enter your password",
},
}),
),
bio: string().transform(
fieldConfig({
fieldType: "textarea",
}),
),
});Provide external types for full TypeScript support.
import { FieldTypes } from "@acp-autoform/mui";
string().transform(
fieldConfig<React.ReactNode, FieldTypes, any, { isImportant?: boolean }>({
inputProps: {
placeholder: "Your name",
},
customData: {
isImportant: true,
},
}),
);See the Customization page for all available fieldConfig options.