From 02a4f0241f65b6a479ffeb5d98416ea3fcef63cb Mon Sep 17 00:00:00 2001 From: zernonia Date: Wed, 24 Apr 2024 00:04:30 +0800 Subject: [PATCH] chore: update example, complete md --- .../.vitepress/theme/components/Callout.vue | 2 +- .../src/content/docs/components/auto-form.md | 510 +++++++++++++++++- .../example/AutoFormInputWithoutLabel.vue | 6 +- .../example/AutoFormInputWithoutLabel.vue | 6 +- 4 files changed, 512 insertions(+), 12 deletions(-) diff --git a/apps/www/.vitepress/theme/components/Callout.vue b/apps/www/.vitepress/theme/components/Callout.vue index b2d5f1ce..d0381be0 100644 --- a/apps/www/.vitepress/theme/components/Callout.vue +++ b/apps/www/.vitepress/theme/components/Callout.vue @@ -19,7 +19,7 @@ defineProps() {{ title }} - + diff --git a/apps/www/src/content/docs/components/auto-form.md b/apps/www/src/content/docs/components/auto-form.md index 72f2e7ea..e240b4a8 100644 --- a/apps/www/src/content/docs/components/auto-form.md +++ b/apps/www/src/content/docs/components/auto-form.md @@ -1,9 +1,517 @@ --- -title: Auto Form +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 + +### 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](http://localhost:5173/docs/components/auto-form.html#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 diff --git a/apps/www/src/lib/registry/default/example/AutoFormInputWithoutLabel.vue b/apps/www/src/lib/registry/default/example/AutoFormInputWithoutLabel.vue index ec94e250..287df014 100644 --- a/apps/www/src/lib/registry/default/example/AutoFormInputWithoutLabel.vue +++ b/apps/www/src/lib/registry/default/example/AutoFormInputWithoutLabel.vue @@ -34,15 +34,11 @@ function onSubmit(values: Record) {
-
- - diff --git a/apps/www/src/lib/registry/new-york/example/AutoFormInputWithoutLabel.vue b/apps/www/src/lib/registry/new-york/example/AutoFormInputWithoutLabel.vue index f2fadc94..67cad8d0 100644 --- a/apps/www/src/lib/registry/new-york/example/AutoFormInputWithoutLabel.vue +++ b/apps/www/src/lib/registry/new-york/example/AutoFormInputWithoutLabel.vue @@ -34,15 +34,11 @@ function onSubmit(values: Record) {
-
- -