Customization
The customization of the components is done by providing a fieldConfig
to your schema fields. This allows you to customize the rendering of the field, add additional props, and more.
With zod, you can use the superRefine
method to add a fieldConfig
to your schema field. For more information, see the Zod documentation.
With yup, you can use the transform
method to add a fieldConfig
to your schema field. For more information, see the Yup documentation. In these examples, we will use Zod.
You should import buildZodFieldConfig
or buildYupFieldConfig
from @autoform/react
and customize it.
import * as z from "zod";
import { buildZodFieldConfig } from "@autoform/react";
import { FieldTypes } from "@autoform/mui";
const fieldConfig = buildZodFieldConfig<
FieldTypes, // You should provide the "FieldTypes" type from the UI library you use
{
isImportant?: boolean; // You can add custom props here
}
>();
const schema = z.object({
username: z.string().superRefine(
fieldConfig({
label: "Username",
inputProps: {
placeholder: "Enter your username",
},
customData: {
isImportant: true, // You can add custom data here
},
})
),
// ...
});
Input props
You can use the inputProps
property to pass props to the input component. You can use any props that the HTML component accepts.
const schema = z.object({
username: z.string().superRefine(
fieldConfig({
inputProps: {
type: "text",
placeholder: "Username",
},
})
),
});
// This will be rendered as:
<input type="text" placeholder="Username" /* ... */ />;
Field type
By default, AutoForm will use the Zod type to determine which input component to use. You can override this by using the fieldType
property.
const schema = z.object({
username: z.string().superRefine(
fieldConfig({
fieldType: "textarea",
})
),
});
The list of available fields depends on the UI library you use - use the autocomplete in your IDE to see the available options.
Custom field types
You can also add your own custom field types. To do this, you need to extend the formComponents
prop of your AutoForm component and add your custom field type.
<AutoForm
formComponents={{
custom: ({ field, label, inputProps }: AutoFormFieldProps) => {
return (
<div>
<input
type="text"
className="bg-red-400 rounded-lg p-4"
// You should always pass the "inputProps" to the input component
// This includes the handlers for "onChange", "onBlur", etc.
{...inputProps}
/>
</div>
);
},
}}
/>;
const fieldConfig = buildZodFieldConfig<
FieldTypes | "custom",
{
isImportant?: boolean;
}
>();
const schema = z.object({
username: z.string().superRefine(
fieldConfig({
fieldType: "custom",
})
),
});
Please note that this will still render the default FieldWrapper
around your input field, which contains the label and error message. If you want to customize this, you can use the fieldWrapper
property (see below).
Description
You can use the description
property to add a description below the field.
const schema = z.object({
username: z.string().superRefine(
fieldConfig({
description:
"Enter a unique username. This will be shown to other users.",
})
),
});
You can use JSX in the description.
Order
If you want to change the order of fields, use the order config. You can pass an arbitrary number where smaller numbers will be displayed first. All fields without a defined order use “0” so they appear in the same order they are defined in
const schema = z.object({
termsOfService: z.boolean().superRefine(
fieldConfig({
order: 1, // This will be displayed after other fields with order 0
})
),
username: z.string().superRefine(
fieldConfig({
order: -1, // This will be displayed first
})
),
email: z.string().superRefine(
fieldConfig({
// Without specifying an order, this will have order 0
})
),
});
Custom field wrapper
You can use the fieldWrapper
property to wrap the field in a custom component. This is useful if you want to add additional elements to the field.
The fieldWrapper
is responsible for rendering the field label and error, so when you use a custom fieldWrapper
, you need to handle these yourself. You can take a look at the FieldWrapperProps
type to see what props are passed to the fieldWrapper
.
const schema = z.object({
email: z.string().superRefine(
fieldConfig({
fieldWrapper: (props: FieldWrapperProps) => {
return (
<>
{props.children}
<p className="text-muted-foreground text-sm">
Don't worry, we won't share your email with anyone!
</p>
</>
);
},
})
),
});
Override UI components
You can also override the default UI components with custom components. This allows you to customize the look and feel of the form.
<AutoForm
uiComponents={{
FieldWrapper: ({ children, label, error }) => {
return (
<div>
<label>{label}</label>
{children}
{error}
</div>
);
},
}}
/>
Form element customization
In addition to overriding UI components, you can also customize the form element itself using the formProps
prop:
<AutoForm
schema={schemaProvider}
onSubmit={handleSubmit}
formProps={{
className: "my-custom-form",
"data-testid": "user-form",
noValidate: true,
onTouchStart: (e) => {
console.log("onTouchStart", e);
},
}}
/>
This allows you to add custom classes, data attributes, or other properties directly to the form element.