svecosystem / formsnap

Functional, accessible, and powerful form components for Svelte. 🫰
https://formsnap.dev
MIT License
593 stars 28 forks source link

Errors not displayed on nested data #146

Closed NDOY3M4N closed 9 months ago

NDOY3M4N commented 9 months ago

Describe the bug

I don't know if this should be considered a bug but when using nested data (from the Superforms docs), FieldErrors doesn't display the errors for the field. The schema used is

// schema.ts
import { z } from 'zod';

export const schema = z.object({
    tags: z
        .object({
            id: z.number().int().min(1),
            name: z.string().min(2)
        })
        .array()
        .default([{ id: 1, name: '' }])
});

When I input 0 in the field, FieldErrors doesn't display the error. I would have to do something like this in order to display it...

{#if $errors.tags?.[i]?.id}
  <br />
  <span class="invalid">{$errors.tags[i].id}</span>
{/if}

Reproduction

Try inputting 0 in the ID field, it should show an error while using FieldError component. In order to display the error, uncomment from line 49 to 52.

https://stackblitz.com/edit/sveltejs-kit-template-default-vjtowp?file=src%2Froutes%2F%2Bpage.svelte

Logs

No response

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (4) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm
    pnpm: 8.14.0 - /usr/local/bin/pnpm
  npmPackages:
    @sveltejs/kit: ^2.0.0 => 2.5.1 
    formsnap: ^0.5.0 => 0.5.0 
    svelte: ^4.2.7 => 4.2.11 
    sveltekit-superforms: ^2.5.0 => 2.5.0 
    zod: ^3.22.4 => 3.22.4

Severity

annoyance

huntabyte commented 9 months ago

Hey there, thanks for the reproduction! I believe I know why this is happening so I will address it as soon as I can!

YummYume commented 9 months ago

Hello. I updated to the latest 0.5.1 version that supposedly fixed this issue, but it seems to be still present for me ? Any error present in nested fields is not displayed. Here is the concerned form for reference.

bravier commented 9 months ago

Hey guys, just to report that I had the exact same issue as @NDOY3M4N and the fix included in 0.5.1 does the job (I verified that errors in nested fields where not displayed with 0.5.0 and are displayed just by updating to 0.5.1). Thanks for the quick fix @huntabyte! :zap:

@YummYume maybe it's the way you form is build that's the issue here? FYI I have this construct on my side (pseudo-code from the first example of course, but you get the idea):

- Form.Fieldset {form} name="tags"
  - {#each $formData.tags as _, index}
    - Form.ElementField {form} name="tags[{index}]"
      - Form.ElementField {form} name="tags[{index}].id"
        - Form.Control let:attrs
          - Input(bind:value={$formData.tags[index].id})
        - Form.FieldErrors
      - Form.ElementField
      - Form.FieldErrors
    - Form.ElementField
  - {/each}
  - Form.FieldErrors
- Form.Fieldset

This link helped me understand the importance of ElementFields: https://formsnap.dev/docs/recipes/dynamic-fields#create-dynamic-fields

YummYume commented 9 months ago

Thank you, @bravier ! I can indeed confirm that it works with the Form.Fieldset (I was using the native one) + Form.ElementField. The only thing that is still not working is the errors for an array nested in an array. But it's at least manageable and I can just display those myself.

A quick explanation of what I mean :

<form>
  <!-- Works fine -->
  <Form.Field name="title" />

  <!-- Works fine -->
  <Form.Fieldset name="questions" />

    <!-- Works fine -->
    <Form.ElementField name="questions[0].question" />

    <!-- Does not work, errors are always empty, but displaying them manually works -->
    <Form.Fieldset name="questions[0].choices" />

      <!-- Works fine too ! -->
      <Form.ElementField name="questions[0].choices[0].label" />

I think the problem is pretty clear, as the doc says :

This component automatically includes the Field component

Fieldset is using the Field element and not the ElementField one.