Skip to content

Instantly share code, notes, and snippets.

@nickludlam
Last active February 4, 2024 14:43
Show Gist options
  • Save nickludlam/08a477d09dbb23246a6354a23b7131a3 to your computer and use it in GitHub Desktop.
Save nickludlam/08a477d09dbb23246a6354a23b7131a3 to your computer and use it in GitHub Desktop.
In this scenario we want to have a <Slider/> component driving a numeric 'volume' value within the form, but also have an input element where you can type the value
<script lang="ts">
import { onDestroy } from "svelte";
import { writable } from "svelte/store";
import type { SuperValidated } from "sveltekit-superforms";
import { formFieldProxy, superForm } from "sveltekit-superforms/client";
import * as Form from "$lib/components/ui/form";
import { Slider } from "$lib/components/ui/slider";
import { settingsFormSchema, type SettingsFormSchema } from "$lib/schema/settings";
export let settingsForm: SuperValidated<SettingsFormSchema>;
// The standard way of using superforms
const settingsSuperForm = superForm(settingsForm, { validators: settingsFormSchema })
// Get a proxy for volume as we want to handle it differently
const { value: volumeProxyValue } = formFieldProxy(settingsSuperForm, 'volume');
// Create a store for volume that specifically stores it in an array, as required by
// Slider, because that can have multiple handles corresponding to multiple values
const sliderVolumeStore = writable([0]);
// Wrap the volume value inside an array for the Slider
let unsubProxyValue = volumeProxyValue.subscribe((value) => {
sliderVolumeStore.set([value]);
});
// Unwrap the Slider array and extract the first value
let unsubSliderVolumeStore = sliderVolumeStore.subscribe((volumeValue) => {
volumeProxyValue.set(volumeValue[0]);
});
// Don't forget to unsubscribe when the component is destroyed
onDestroy(() => {
unsubProxyValue();
unsubSliderVolumeStore();
});
</script>
<Form.Root method="POST" form={settingsSuperForm} controlled schema={settingsFormSchema} let:config debug>
<Form.Field {config} name="volume">
<Form.Item class="mb-8">
<Form.Label>Volume</Form.Label>
<Form.Input />
<Form.Description>How loud is it?</Form.Description>
<Form.Validation />
</Form.Item>
</Form.Field>
<Form.Field {config} name="volume">
<Form.Item class="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4 shadow mb-8">
<Form.Label>Volume</Form.Label>
<Slider bind:value={$sliderVolumeStore} />
<Form.Description>You can also set it with a slider</Form.Description>
<Form.Validation />
</Form.Item>
</Form.Field>
</Form.Root>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment