feat: support custom form state

This commit is contained in:
zernonia 2024-04-19 14:10:59 +08:00
parent 1c562463b2
commit b07b4d4d96
2 changed files with 37 additions and 12 deletions

View File

@ -1,12 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import * as z from 'zod' import * as z from 'zod'
import { h, reactive } from 'vue' import { h, reactive, ref } from 'vue'
import { useForm } from 'vee-validate' import { useForm } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod' import { toTypedSchema } from '@vee-validate/zod'
import { Button } from '@/lib/registry/new-york/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'
import { toast } from '@/lib/registry/new-york/ui/toast' import { toast } from '@/lib/registry/new-york/ui/toast'
import type { Config } from '@/lib/registry/new-york/ui/auto-form' import type { Config } from '@/lib/registry/new-york/ui/auto-form'
import { AutoForm, AutoFormField } from '@/lib/registry/new-york/ui/auto-form' import { AutoForm as AutoFormComponent, AutoFormField } from '@/lib/registry/new-york/ui/auto-form'
const schema = z.object({ const schema = z.object({
guestListName: z.string(), guestListName: z.string(),
@ -30,11 +30,21 @@ function onSubmit(values: Record<string, any>) {
description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))), description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),
}) })
} }
const form = useForm({
keepValuesOnUnmount: true, // make sure the array/object field doesn't destroy the linked field
validationSchema: toTypedSchema(schema),
})
form.setValues({
guestListName: 'testing 123',
})
</script> </script>
<template> <template>
<AutoForm <AutoFormComponent
class="w-2/3 space-y-6" class="w-2/3 space-y-6"
:form="form"
:schema="schema" :schema="schema"
:field-config="{ :field-config="{
guestListName: { guestListName: {
@ -57,5 +67,5 @@ function onSubmit(values: Record<string, any>) {
<Button type="submit"> <Button type="submit">
Submit Submit
</Button> </Button>
</AutoForm> </AutoFormComponent>
</template> </template>

View File

@ -1,8 +1,8 @@
<script setup lang="ts" generic="U extends ZodRawShape, T extends ZodObject<U>"> <script setup lang="ts" generic="U extends ZodRawShape, T extends ZodObject<U>">
import { computed } from 'vue' import { computed, ref } from 'vue'
import type { ZodAny, ZodObject, ZodRawShape, z } from 'zod' import type { ZodAny, ZodObject, ZodRawShape, z } from 'zod'
import { toTypedSchema } from '@vee-validate/zod' import { toTypedSchema } from '@vee-validate/zod'
import type { GenericObject } from 'vee-validate' import type { FormContext, GenericObject } from 'vee-validate'
import { getBaseType, getDefaultValueInZodStack } from './utils' import { getBaseType, getDefaultValueInZodStack } from './utils'
import type { Config, ConfigItem, Shape } from './interface' import type { Config, ConfigItem, Shape } from './interface'
import AutoFormField from './AutoFormField.vue' import AutoFormField from './AutoFormField.vue'
@ -10,6 +10,7 @@ import { Form } from '@/lib/registry/new-york/ui/form'
const props = defineProps<{ const props = defineProps<{
schema: T schema: T
form?: FormContext<GenericObject>
fieldConfig?: Config<z.infer<T>> fieldConfig?: Config<z.infer<T>>
}>() }>()
@ -38,14 +39,28 @@ const shapes = computed(() => {
return val return val
}) })
const formSchema = computed(() => toTypedSchema(props.schema)) const formComponent = computed(() => props.form ? 'form' : Form)
const formComponentProps = computed(() => {
const formSchema = toTypedSchema(props.schema)
if (props.form) {
return {
onSubmit: props.form.handleSubmit(val => emits('submit', val)),
}
}
else {
return {
keepValues: true,
validationSchema: formSchema,
onSubmit: (val: GenericObject) => emits('submit', val),
}
}
})
</script> </script>
<template> <template>
<Form <component
:keep-values="true" :is="formComponent"
:validation-schema="formSchema" v-bind="formComponentProps"
@submit="emits('submit', $event)"
> >
<template v-for="(shape, key) of shapes" :key="key"> <template v-for="(shape, key) of shapes" :key="key">
<slot <slot
@ -62,5 +77,5 @@ const formSchema = computed(() => toTypedSchema(props.schema))
</template> </template>
<slot :shapes="shapes" /> <slot :shapes="shapes" />
</Form> </component>
</template> </template>