--- title: AutoForm description: Automatically generate a form from Zod schema. primitive: https://vee-validate.logaretm.com/v4/guide/overview/ --- Credit: Heavily inspired by [AutoForm](https://github.com/vantezzen/auto-form) by Vantezzen ## What is AutoForm AutoForm is a drop-in form builder for your internal and low-priority forms with existing zod schemas. For example, if you already have zod schemas for your API and want to create a simple admin panel to edit user profiles, simply pass the schema to AutoForm and you're done. ## Installation ### Run the following command ```bash npx shadcn-vue@latest update form npx shadcn-vue@latest add auto-form ``` ## Field types Currently, these field types are supported out of the box: - boolean (checkbox, switch) - date (date picker) - enum (select, radio group) - number (input) - string (input, textfield) - file (file) You can add support for other field types by adding them to the `INPUT_COMPONENTS` object in `auto-form/constants.ts`. ## Zod configuration ### Validations Your form schema can use any of zod's validation methods including refine. ⚠️ However, there's a known issue with Zod’s `refine` and `superRefine` not executing whenever some object keys are missing. [Read more](https://github.com/logaretm/vee-validate/issues/4338) ### Descriptions You can use the `describe` method to set a label for each field. If no label is set, the field name will be used and un-camel-cased. ```ts const formSchema = z.object({ username: z.string().describe('Your username'), someValue: z.string(), // Will be "Some Value" }) ``` You can also configure the label with [`fieldConfig`](#label) too. ### Optional fields By default, all fields are required. You can make a field optional by using the `optional` method. ```ts const formSchema = z.object({ username: z.string().optional(), }) ``` ### Default values You can set a default value for a field using the `default` method. ```ts const formSchema = z.object({ favouriteNumber: z.number().default(5), }) ``` If you want to set default value of date, convert it to Date first using `new Date(val)`. ### Sub-objects You can nest objects to create accordion sections. ```ts const formSchema = z.object({ address: z.object({ street: z.string(), city: z.string(), zip: z.string(), // You can nest objects as deep as you want nested: z.object({ foo: z.string(), bar: z.string(), nested: z.object({ foo: z.string(), bar: z.string(), }), }), }), }) ``` Like with normal objects, you can use the `describe` method to set a label and description for the section: ```ts const formSchema = z.object({ address: z .object({ street: z.string(), city: z.string(), zip: z.string(), }) .describe('Your address'), }) ``` ### Select/Enums AutoForm supports `enum` and `nativeEnum` to create select fields. ```ts const formSchema = z.object({ color: z.enum(['red', 'green', 'blue']), }) enum BreadTypes { // For native enums, you can alternatively define a backed enum to set a custom label White = 'White bread', Brown = 'Brown bread', Wholegrain = 'Wholegrain bread', Other, } // Keep in mind that zod will validate and return the enum labels, not the enum values! const formSchema = z.object({ bread: z.nativeEnum(BreadTypes), }) ``` ### Arrays AutoForm supports arrays _of objects_. Because inferring things like field labels from arrays of strings/numbers/etc. is difficult, only objects are supported. ```ts const formSchema = z.object({ guestListName: z.string(), invitedGuests: z .array( // Define the fields for each item z.object({ name: z.string(), age: z.number(), }) ) // Optionally set a custom label - otherwise this will be inferred from the field name .describe('Guests invited to the party'), }) ``` 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. ```ts const formSchema = z.object({ guestListName: z.string(), invitedGuests: z .array( // Define the fields for each item z.object({ name: z.string(), age: z.number(), }) ) .describe('Guests invited to the party') .default([ { name: 'John', age: 24, }, { name: 'Jane', age: 20, }, ]), }) ``` ## Field configuration As zod doesn't allow adding other properties to the schema, you can use the `fieldConfig` prop to add additional configuration for the UI of each field. ```vue ``` ### Label You can use the `label` property to customize label if you want to overwrite the pre-defined label via [Zod's description](#descriptions). ```vue ``` ### Description You can use the `description` property to add a description below the field. ```vue ``` ### 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. ```vue // This will be rendered as: ``` Disabling the label of an input can be done by using the `showLabel` property in `inputProps`. ```vue ``` ### Component By default, AutoForm will use the Zod type to determine which input component to use. You can override this by using the `component` property. ```vue ``` The complete list of supported field types is typed. Current supported types are: - `checkbox` (default for booleans) - `switch` - `date` (default for dates) - `select` (default for enums) - `radio` - `textarea` Alternatively, you can pass a Vue component to the `component` property to use a custom component. In `CustomField.vue` ```vue ``` Pass the above component in `fieldConfig`. ```vue ``` ### Named slot You can use Vue named slot to customize the rendered `AutoFormField`. ```vue ``` ### Accessing the form data There are two ways to access the form data: ### @submit The preferred way is to use the `submit` emit. This will be called when the form is submitted and the data is valid. ```vue ``` ### Controlled form By passing the `form` as props, you can control and use the method provided by `Form`. ```vue ``` ### Submitting the form You can use any `button` component to create a submit button. Most importantly is to add attributes `type="submit"`. ```vue ``` ### Adding other elements All children passed to the `AutoForm` component will be rendered below the form. ```vue ``` ### Dependencies AutoForm allows you to add dependencies between fields to control fields based on the value of other fields. For this, a `dependencies` array can be passed to the `AutoForm` component. ```vue ``` The following dependency types are supported: - `DependencyType.HIDES`: Hides the target field when the `when` function returns true - `DependencyType.DISABLES`: Disables the target field when the `when` function returns true - `DependencyType.REQUIRES`: Sets the target field to required when the `when` function returns true - `DependencyType.SETS_OPTIONS`: Sets the options of the target field to the `options` array when the `when` function returns true The `when` function is called with the value of the source field and the value of the target field and should return a boolean to indicate if the dependency should be applied. Please note that dependencies will not cause the inverse action when returning `false` - for example, if you mark a field as required in your zod schema (i.e. by not explicitly setting `optional`), returning `false` in your `REQURIES` dependency will not mark it as optional. You should instead use zod's `optional` method to mark as optional by default and use the `REQURIES` dependency to mark it as required when the dependency is met. Please note that dependencies do not have any effect on the validation of the form. You should use zod's `refine` method to validate the form based on the value of other fields. You can create multiple dependencies for the same field and dependency type - for example to hide a field based on multiple other fields. This will then hide the field when any of the dependencies are met. ## Example ### Basic ### Input Without Label This example shows how to use AutoForm input without label. ### Sub Object Automatically generate a form from a Zod schema. ### Controlled This example shows how to use AutoForm in a controlled way. ### Confirm Password Refined schema to validate that two fields match. ### API Example The form select options are fetched from an API. ### Array support You can use arrays in your schemas to create dynamic forms. ### Dependencies Create dependencies between fields.