Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snapshots with componentized form #412

Open
singingwolfboy opened this issue Apr 19, 2024 · 2 comments
Open

Snapshots with componentized form #412

singingwolfboy opened this issue Apr 19, 2024 · 2 comments

Comments

@singingwolfboy
Copy link

singingwolfboy commented Apr 19, 2024

I'm trying to factor out my form into a component, as described in the documentation. However, I can't figure out how to export a snapshot of my form when doing so. The documentation clearly states that a snapshot object must be exported from a +page.svelte or +layout.svelte file; exporting it from a component file won't work.

So if my form component looks like this:

<!-- MyForm.svelte -->
<script lang="ts">
  import { superForm, type SuperValidated, type Infer } from 'sveltekit-superforms/client';
  import { schema } from './schema';

  export let data: SuperValidated<Infer<typeof schema>>;

  const form = superForm(data, {
    SPA: true,
    validators: zod(schema),
    ...
  });
  const { form: formData, capture, restore, enhance } = form;
  // `capture` and `restore` are available here, inside the component
</script>

<form use:enhance method="POST">
  <!-- form fields here -->
</form>

And my page looks like this:

<!-- +page.svelte -->
<script lang="ts">
  import MyForm from './MyForm.svelte'

  export let data;
  // need to get the `capture` and `restore` functions here, so I can export them from the page!
</script>

<MyForm data={data.form} />

How do I make this work?

Note that this seems to be fundamentally the same question as #162, but I don't understand the resolution to that issue.

@singingwolfboy singingwolfboy added the bug Something isn't working label Apr 19, 2024
@ciscoheat
Copy link
Owner

You need to export a custom capture and restore object, similar to this, and then bind it to the component, so the component can modify it.

@ciscoheat ciscoheat removed the bug Something isn't working label Apr 19, 2024
@singingwolfboy
Copy link
Author

I ended up doing this:

<!-- MyForm.svelte -->
<script lang="ts">
  import type { Snapshot } from '@sveltejs/kit';
  import { superForm, type SuperValidated, type Infer } from 'sveltekit-superforms/client';
  import { schema } from './schema';

  export let data: SuperValidated<Infer<typeof schema>>;
  export let snapshot: Snapshot;

  const form = superForm(data, {
    SPA: true,
    validators: zod(schema),
    ...
  });
  const { form: formData, capture, restore, enhance } = form;
  snapshot = { capture, restore }
</script>

<form use:enhance method="POST">
  <!-- form fields here -->
</form>
<!-- +page.svelte -->
<script lang="ts">
  import type { Snapshot } from '@sveltejs/kit';
  import MyForm from './MyForm.svelte'

  export let data;
  export let snapshot: Snapshot = { capture() {}, restore(snapshot) {} };
</script>

<!-- not sure why this is needed, but it doesn't seem to work without it... -->
<svelte:options accessors />

<MyForm data={data.form} bind:snapshot />

Is that basically what you had in mind? I'm not sure if I need to be concerned about the accessors thing, or why it's needed. I'm also a bit surprised that this works; I thought that the restore function would run when the page component loaded, before the child <MyForm> component had a chance to set it to something meaningful. It seems to work, but I don't know if this introduces a race condition or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants