sveltekit-superforms icon indicating copy to clipboard operation
sveltekit-superforms copied to clipboard

Use Svelte 5 Runes for form data

Open Tyler-Petrov opened this issue 8 months ago • 7 comments

First off I love the library, and it's helped my get a handle of my forms. With that in mind I have a suggestion.

Is your feature request related to a problem? Please describe. Now that Svelte 5 Runes are a thing I'm not enjoying working with the SuperFormData store. I end up defining the super form, then setting a separate variable for the form data store itself so I can subscribe to it using bind:value on an input. As far as I can tell Svelte doesn't support subscribing to a property of an object. This really isn't a problem if there's only on form on a page, but let's be honest, that rarely happens. Most pages have 2 or more pages, and with a 5 to 10 pages like this things get crazy fast.

This would be a basic form that I would define

<script lang="ts">
	import SuperDebug, { superForm } from 'sveltekit-superforms';
	import type { PageData } from './$types';
	import { valibotClient } from 'sveltekit-superforms/adapters';
	import * as Form from '$lib/components/ui/form';
	import { Input } from '$shadcn/input';
	import { Button } from '$shadcn/button';
	import * as v from 'valibot';

	let { data }: { data: PageData } = $props();

	/* Defined somewhere the client and server can see it */
	const testVali = v.object({
		firstName: v.pipe(v.string()),
		lastName: v.pipe(v.string())
	});

	const testForm = superForm(data.testForm, {
		validators: valibotClient(testVali)
	});
	const testFormData = testForm.form;
</script>

<SuperDebug data={$testFormData} />

<form method="post" use:testForm.enhance>
	<input name="firstName" bind:value={$testFormData.firstName} />
	<input name="lastName" bind:value={$testFormData.lastName} />

	<button type="submit">Submit this here form</button>
</form>

Describe the solution you'd like What I would like to see is a self contained class that can be built and extended with the form data as a Rune, so no $ subscribe is needed. Extending this class would be helpful for a form that is inside of a modal or sheet. The open property could be set of the new class, and keep everything self contained.

I'd like to see an implementation similar to this.

<script lang="ts">
	import SuperDebug from 'sveltekit-superforms';
	import type { PageData } from './$types';
	import { valibotClient } from 'sveltekit-superforms/adapters';
	import * as Form from '$lib/components/ui/form';
	import { Input } from '$shadcn/input';
	import { Button } from '$shadcn/button';
	import * as v from 'valibot';

	let { data }: { data: PageData } = $props();

	/* Defined somewhere the client and server can see it */
	const testVali = v.object({
		firstName: v.pipe(v.string()),
		lastName: v.pipe(v.string())
	});

	const testForm = SuperForm(data.testForm, {
		validators: valibotClient(testVali)
	});
</script>

<SuperDebug data={testForm.data} />

<form method="post" use:testForm.enhance>
	<input name="firstName" bind:value={testForm.data.firstName} />
	<input name="lastName" bind:value={testForm.data.lastName} />

	<button type="submit">Submit this here form</button>
</form>

Describe alternatives you've considered I've tried building a class myself, but I keep running into the stores being an issue to subscribe to. I'm sure there's a somewhat simple way around it, but it seems like the idea I laid out would be helpful for others as well.

Tyler-Petrov avatar Mar 07 '25 14:03 Tyler-Petrov