pablo-abc / felte

An extensible form library for Svelte, Solid and React
https://felte.dev
MIT License
1.01k stars 45 forks source link

Nested forms update the parent data store #296

Open t348575 opened 3 months ago

t348575 commented 3 months ago

Describe the bug

I have a strange use case where some nested components also have their own <form> with their own validation & submission, and noticed that the child components appear to also update the data store of the parent component.

Which package/s are you using?

felte (Svelte), @felte/validator-zod

Environment

To reproduce

App.svelte

<script lang="ts">
  import { createForm } from 'felte';
  import * as zod from 'zod';
  import { validator } from "@felte/validator-zod";
  import Child from './Child.svelte'

  type Data = {
    email: string;
    password: string;
  }

  let submitted: Data | undefined;

  const schema = zod.object({
    a: zod.string()
  })
  const { form, data } = createForm<Data>({
    onSubmit(values) {
      submitted = values;
    },
    extend: validator({schema}),
  });

  $: console.log($data)

</script>

<main>
  <h1>Basic Example - Svelte</h1>
  <form use:form>
    <fieldset>
      <legend>Sign In</legend>
      <label for="a">Email:</label>
      <input type="text" name="a" id="a" />
    </fieldset>
    <button type="submit">Submit</button>
    <button type="reset">Reset</button>
    <Child/>
  </form>
  {#if submitted}
    <section>
      <h2>Submitted values</h2>
      <pre>{JSON.stringify(submitted, null, 2)}</pre>
    </section>
  {/if}
</main>

Child.svelte

<script lang="ts">
  import { createForm } from 'felte';
  import * as zod from 'zod';
  import { validator } from "@felte/validator-zod";

  type Data = {
    email: string;
    password: string;
  }

  let submitted: Data | undefined;

  const schema = zod.object({
    child_a: zod.string(),
  })
  const child = createForm<Data>({
    onSubmit(values) {
      submitted = values;
    },
    extend: validator({schema}),
  });

</script>
<main>
  <h2>Child component:</h2>
  <form use:child.form>
    <fieldset>
      <legend>Sign In</legend>
      <label for="child_a">Email:</label>
      <input type="text" name="child_a" id="child_a" />
    </fieldset>
  </form>
</main>

Small reproduction example

https://stackblitz.com/edit/vitejs-vite-kfgcfh?file=src%2FApp.svelte

Screenshots

No response

Additional context

No response

Jylth commented 1 month ago

Same issue on Solid.js.

This is a very annoying issue when building more complex views which are highly composable. It reduces the dev UX a lot and forces you to be careful or to find other ways to compose views through Portals which feels very hacky.

Thank you for your support and hard work.

I can help if needed.