Skip to content

Commit b303b64

Browse files
committed
docs: improved form & migration documentation
1 parent 40b0fb8 commit b303b64

File tree

6 files changed

+377
-16
lines changed

6 files changed

+377
-16
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<script setup lang="ts">
2+
import * as z from 'zod'
3+
4+
const REFERRAL_SOURCES = [
5+
'Linkedin',
6+
'Facebook',
7+
'Instagram',
8+
'Friend',
9+
'Internet',
10+
'Other',
11+
]
12+
13+
enum Age {
14+
'10-13' = 10,
15+
'14-16' = 14,
16+
'16-18' = 16,
17+
'19-22' = 19,
18+
'23+' = 23,
19+
}
20+
21+
const ageKeys = Object.keys(Age).filter(key => Number.isNaN(Number(key)))
22+
23+
const schema = z.object({
24+
first_name: z.string()
25+
.nonempty({ error: 'First name is required' })
26+
.meta({ title: 'First Name' }),
27+
age: z.enum(ageKeys, { message: 'Age is required' })
28+
.meta({ title: 'Age' }),
29+
location: z.string({ error: 'Location is required' })
30+
.meta({ title: 'Location', description: 'City or town where you live' }),
31+
organization: z.string({ error: 'Organization is required' })
32+
.meta({ title: 'Organization', description: 'Your school, university, or company' }),
33+
is_vegetarian: z.boolean({ error: 'Selection is required' })
34+
.meta({ title: 'Dietary preferences' }),
35+
marketing_consent: z.boolean()
36+
.meta({
37+
title: 'Do you want to receive information about future Hack4Krak events?',
38+
autoForm: { floatRight: true },
39+
}),
40+
referral_source: z
41+
.array(z.enum(REFERRAL_SOURCES))
42+
.min(1, 'Please select at least one referral source.')
43+
.meta({ title: 'How did you hear about us? (multiple choice)' }),
44+
})
45+
46+
// Normally you could use `.default()` in the schema, but sometimes you need
47+
// to fill the initial state from an external source, like an API call.
48+
const state = {
49+
age: 10,
50+
}
51+
52+
async function onSubmit(_data: z.infer<typeof schema>) {
53+
// Send data to the server
54+
// BTW I suggest using nuxt-auto-form for that
55+
//
56+
// await useNuxtApp().$auth('/account/submit_personal_information', {
57+
// method: 'POST',
58+
// body: data
59+
// })
60+
61+
useToast().add({ title: 'Success', description: 'Data successfully submitted', color: 'success' })
62+
63+
await refreshNuxtData()
64+
navigateTo('/panel')
65+
}
66+
</script>
67+
68+
<template>
69+
<div class="">
70+
<h1 class="text-2xl font-medium mb-2">
71+
Provide additional information
72+
</h1>
73+
74+
<div class="text-sm mb-4 space-y-3">
75+
<p>
76+
Before you start using the site, please provide additional account information.
77+
</p>
78+
<p>
79+
The information you provide here will only be visible to the event organizers and is required for the event to run smoothly.
80+
</p>
81+
</div>
82+
83+
<AutoForm :schema="schema" :initial-state="state" @submit="onSubmit">
84+
<template #is_vegetarian="{ field, state: stateValue }">
85+
<USelect
86+
v-model="stateValue[field]"
87+
:items="[
88+
{
89+
label: 'Meat diet',
90+
value: false,
91+
},
92+
{
93+
label: 'Vegan/vegetarian diet',
94+
value: true,
95+
},
96+
]"
97+
/>
98+
</template>
99+
</AutoForm>
100+
</div>
101+
</template>

docs/app/components/examples/Test.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,8 @@ const schema = z.object({
2323
</script>
2424

2525
<template>
26-
<AutoForm :schema="schema" />
26+
<AutoForm
27+
:schema="schema"
28+
:config="{ submit: { props: { label: 'Send!!!' } } }"
29+
/>
2730
</template>

docs/content/1.getting-started/3.usage.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Usage
2+
title: Basic usage
33
description: Learn how to auto-generate your first form.
44
---
55

@@ -33,14 +33,14 @@ Use the `AutoForm` component to automatically generate the form:
3333

3434
Make sure the schema is available in your component’s setup scope.
3535

36-
## Customization
36+
## Next steps
3737

38-
You can customize the form using the following options:
38+
Good job! You have successfully created your first auto-generated form.
39+
Now you can explore more advanced features and customization options.
3940

40-
- [Config](/customization/config) - modify default components and module settings
41-
- [Fields](/customization/fields) - customize the rendering, title, and description of individual fields
42-
- [SubmitButton](/customization/submit_button) - customize the submit button appearance and behavior
43-
- [Slots](/customization/slots) - create fully custom input fields for maximum flexibility
41+
- [AutoForm](/components/form) - learn more about the `<NuxtAutoForm>` component
42+
- [Customization](/components/form#customization) - explore various ways to customize the form
43+
- [Migration](/getting-started/migration) - learn how to migrate to Nuxt Auto Form
4444

4545
## Example
4646

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
---
2+
title: Migration
3+
description: Learn how to migrate your existing Nuxt forms to Nuxt Auto Form.
4+
---
5+
6+
## Prerequisites
7+
8+
Before migrating:
9+
- Follow the [Installation](/getting-started/installation) guide to set up Nuxt Auto Form in your project.
10+
- Have a basic understanding of the [NuxtAutoForm](/components/form) component and its customization.
11+
- Ensure Zod **v4** is installed.
12+
13+
## (Optional) Customize Your Default Config
14+
15+
If you already know that you have some default custom styles or components, update your [app.config.ts](/customization/config) before starting:
16+
17+
```ts-type
18+
autoForm: {
19+
submit: {
20+
props: { label: 'Send form', class: 'w-full flex justify-center' },
21+
},
22+
},
23+
```
24+
25+
## Migration
26+
27+
::steps{level="4"}
28+
29+
#### Find your existing forms
30+
31+
Search for `<UForm>` in your codebase. Most editors support “search everywhere”:
32+
33+
::tip
34+
Shortcut example (VSCode / JetBrains): :kbd{value="meta"} :kbd{value="Shift"} :kbd{value="F"}.
35+
::
36+
37+
#### Add `AutoForm` component
38+
39+
Inside the `<template>` near your `<UForm>` component, insert the `AutoForm`:
40+
41+
```vue
42+
<AutoForm :schema="schema" @submit="onSubmit" />
43+
```
44+
45+
#### Update your submit method
46+
47+
Update your `onSubmit` function to accept form data directly:
48+
49+
```diff
50+
<script setup lang="ts">
51+
import * as z from 'zod'
52+
53+
-type Schema = z.output<typeof schema>
54+
55+
const schema = z.object({
56+
new_password: z.string()
57+
})
58+
59+
-const state = reactive<Partial<Schema>>({
60+
- new_password: undefined,
61+
-})
62+
63+
-async function onSubmit(event: FormSubmitEvent<Schema>) {
64+
+async function onSubmit(data: z.infer<typeof schema>) {
65+
- event.preventDefault()
66+
- console.log(event.data)
67+
console.log(data)
68+
}
69+
```
70+
71+
#### Apply Customization Options
72+
73+
Now comes the fun part! You can make your form look exactly how you want using [Customization](/components/form#customization) options.
74+
75+
For most cases, simply add the [`meta`](/customization/fields) attribute to your fields inside Zod schema.
76+
77+
```diff
78+
const schema = z.object({
79+
- new_password: z.string()
80+
+ new_password: z.string().meta({ title: 'New account password', hint: 'Use at least 8 characters' })
81+
})
82+
```
83+
84+
And then if you need it, customize [`config`](/customization/config) property to the `AutoForm` component:
85+
86+
```vue
87+
<AutoForm :schema="schema" @submit="onSubmit" :config="{ submit: { props: { label: 'Confirm' } } }" />
88+
```
89+
90+
#### Remove Old `UForm` Component
91+
92+
We left the old `<UForm>` component temporarily so you can compare it with your new AutoForm and ensure everything works and looks correct.
93+
94+
Once you are confident the migration is complete, you can safely remove:
95+
- The `<UForm>` component from your templates
96+
- Any related state, imports, or helper code like `Schema` or `state`
97+
98+
#### Good job! Repeat for all your UForms
99+
100+
::
101+
102+
## Next steps
103+
104+
While you’re refactoring your forms, take a moment to explore [Zod's Good Practices](/good-practises/zod).
105+
Applying some of these practices can add auto imports, reduce code duplication and more.
106+
107+
## Troubleshooting
108+
109+
This project is in `Beta`{color=warning} stage. There may be some bugs or missing features.
110+
If you find something that doesn't work as expected or you are unsure how to migrate your form.
111+
112+
- Feel free to open [a new GitHub issue](https://github.com/Norbiros/nuxt-auto-form/issues/new/choose).
113+
- Chat with me on [Discord](https://discord.com/users/770620808644919307) (`@norbiros`).
114+
115+
## Examples
116+
117+
::tip
118+
If you want to see how I migrated a real world application to `nuxt-auto-form`, check out the [Hack4KrakSite PR #637](https://github.com/Hack4Krak/Hack4KrakSite/pull/637/commits/2e5e89bdfab8a7a4369b796807fc84e031ffc3c6).
119+
::
120+
121+
```diff
122+
<script setup lang="ts">
123+
import * as z from 'zod'
124+
125+
-type Schema = z.output<typeof schema>
126+
127+
const schema = z.object({
128+
- new_password: z.string()
129+
+ new_password: z.string().meta({ title: 'New account password' })
130+
})
131+
132+
-const loading = ref(false)
133+
-const state = reactive<Partial<Schema>>({
134+
- new_password: undefined,
135+
-})
136+
137+
-async function onSubmit(event: FormSubmitEvent<Schema>) {
138+
+async function onSubmit(data: z.infer<typeof schema>) {
139+
- event.preventDefault()
140+
- console.log(event.data)
141+
console.log(data)
142+
}
143+
</script>
144+
145+
<template>
146+
<div>
147+
<h1 class="text-2xl font-medium">
148+
Reset password
149+
</h1>
150+
151+
- <UForm :schema="schema" :state="state" class="space-y-4 text-center" @submit="onSubmit">
152+
- <UFormField label="New account password" name="new_password">
153+
- <UInput v-model="state.new_password" class="w-full" />
154+
- </UFormField>
155+
- <div class="space-y-2">
156+
- <UButton type="submit" class="w-full text-center inline rounded-3xl py-2 bg-neutral-300">
157+
- Confirm
158+
- </UButton>
159+
- </div>
160+
- </UForm>
161+
+ <AutoForm :schema="schema" @submit="onSubmit" :config="{ submit: { props: { label: 'Confirm' } } }" />
162+
</div>
163+
</template>
164+
```

0 commit comments

Comments
 (0)