nuxt / ui

A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.
https://ui.nuxt.com
MIT License
4.05k stars 515 forks source link

Nested Zod schemas validation fails #1517

Closed Stf-F closed 8 months ago

Stf-F commented 8 months ago

Environment

------------------------------
- Operating System: Darwin
- Node Version:     v18.19.1
- Nuxt Version:     3.10.3
- CLI Version:      3.10.1
- Nitro Version:    2.9.3
- Package Manager:  npm@10.2.4
- Builder:          -
- User Config:      devtools, extends, colorMode, modules, primevue, dir, image, imports, vuefire, runtimeConfig, nitro
- Runtime Modules:  nuxt-vuefire@1.0.2, @vueuse/nuxt@10.9.0, @nuxt/image@1.4.0, @formkit/nuxt@0.17.5, @nuxtjs/html-validator@1.6.0, @nuxt/test-utils/module@3.11.0, @nuxt/ui@2.14.2, @nuxt/fonts@0.2.1, nuxt-primevue@0.3.1
- Build Modules:    -
------------------------------

But also reproduced on Stackblitz with:

------------------------------
- Operating System: Linux
- Node Version:     v18.18.0
- Nuxt Version:     3.10.3
- CLI Version:      3.10.1
- Nitro Version:    2.9.3
- Package Manager:  npm@10.2.3
- Builder:          -
- User Config:      devtools, modules
- Runtime Modules:  @nuxt/ui@2.14.2
- Build Modules:    -
------------------------------

Version

2.14.2

Reproduction

The repo with the repro: https://stackblitz.com/edit/nuxt-starter-c7fdv5?file=schemas%2Findex.ts,app.vue,nuxt.config.ts,pages%2Findex.vue

Description

I have a complex form where I compose several zod schemas together to create a final validation schema. I have tried using .object and .extend and I always come to the same conclusion, nested schemas with nested reactive properties are not validated. This will not be validated at all:

const schema = z.object({
foo: FooSchema,
bar: BarSchema
})

With the following state :

const state = reactive({
 foo: {
 // stuff
 },
  bar: {
 // stuff
 }
})

And this will only validate the properties of the FooSchema as they sit at the root, but bar validation will not work.

const schema = FooSchema.extend({
bar: BarSchema
})

With :

const state = reactive({
foo_key_1: "", // is validated by the schema
foo_key_2: "", // is validated by the schema
  bar: { 
 // anything in here is _not_ validated 
 }
})

This is really tricky and causing me a ton of grief. Nested data structures are not uncommon in forms and it would be really nice to get support for this.
Thanks,

Additional context

No response

Logs

No response

Gerbuuun commented 8 months ago

When validating, the messages are passed to the form using the name property: https://ui.nuxt.com/components/form#error-event So when you have a state with nested values the name should look like so: <FormGroup name="parent.nestedValue">

Stf-F commented 8 months ago

When validating, the messages are passed to the form using the name property: https://ui.nuxt.com/components/form#error-event So when you have a state with nested values the name should look like so: <FormGroup name="parent.nestedValue">

I did see that but did not connect the dots. It does work indeed. The docs could use an example with nested structures I suppose. Thanks @Gerbuuun 👍