sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
77.59k stars 4.04k forks source link

Svelte 5: Two-way-binding of superforms $formData is broken if passed as arg in render snippet #11499

Open ryou90 opened 2 months ago

ryou90 commented 2 months ago

Describe the bug

Hi, I can pass the superforms $formData state as arg in the @render formField($formData) snippet. Everthing works so far. The data is displayed correctly in the form. But if I enter a new value for the url field, it is immediately reset to the original value. It looks as if the two-way reactivity is broken in the snippet and the DOM is rerendered with the original values.

Reproduction

Minimal code snippet

// FormRoot.svelte
<script lang="ts">
    import {
        superForm,
    } from 'sveltekit-superforms'
    import { valibot, valibotClient } from 'sveltekit-superforms/adapters'
    import * as v from 'valibot'
    let {
        data = {},
        formFields,
    }: {
        data: any
        formFields: Snippet<[form: any, formData: any]>
    } = $props()

   const schema = v.object({
       url: v.string([v.minLength(3)]),
    })

   let options = {
        SPA: true,
        resetForm: false,
        applyAction: false,
        validators: valibotClient(schema),
}

    const form:  = superForm(
        data.form,
        options
    )
    const { form: formData, enhance } = form
</script>

<form method="POST" use:enhance >
    {@render formFields(form, $formData)}
</form>
//+page.svelte
<script lang="ts">
    import { FormRoot } from './FormRoot.svelte'
    let { data, open = $bindable(), ...props }: { data: any; open: boolean } = $props()
</script>

{#snippet formFields(form, $formData)}
        <input bind:value={$formData.url} />
{/snippet}

<FormRoot {data} {formFields} bind:open {...props} />
//+page.ts

import { superValidate } from 'sveltekit-superforms'
import { valibot } from 'sveltekit-superforms/adapters'
import type { PageLoad } from './$types'

export const load: PageLoad = async ({ params, fetch }) => {
    const id = parseInt(params.id)
    // TODO: Get publisher from workspace

    const defaults = {
        url: 'https://example.com',
    }

   const schema = v.object({
       url: v.string([v.minLength(3)]),
    })
    const form = await superValidate(valibot(schema, { defaults }))
    return { form }
}

Logs

No response

System Info

System:
    OS: macOS 14.4.1
    CPU: (8) arm64 Apple M2
    Memory: 1.00 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    bun: 1.1.7 - /private/tmp/bun-node-b0b7db5c0/bun
  Browsers:
    Edge: 124.0.2478.80
    Safari: 17.4.1

Severity

annoyance

Conduitry commented 2 months ago

Please provide a complete minimal reproduction. This contains several references to external files.

ryou90 commented 2 months ago

I have simplified and expanded the example as much as possible.

dummdidumm commented 2 months ago

Please use something like sveltelab.dev or Stackblitz and post a link to a proper reproduction.