[READ-ONLY] Mirror of https://github.com/probablykasper/niceform. Convenient form validation and typing for SvelteKit
0

Configure Feed

Select the types of activity you want to include in your feed.

Add example usage

authored by

Kasper and committed by
GitHub
(Feb 1, 2025, 8:54 AM +0100) cd93b414 3abd7cf6

+70 -1
+70 -1
README.md
··· 1 1 # niceform 2 - Convenient form validation and typing for SvelteKit. Based on Superforms and Zod 2 + Convenient form validation and typing for SvelteKit. Based on Superforms and Zod. 3 + 4 + Might turn this into an actual package later 5 + 6 + ### Example `+page.server.ts`: 7 + ```ts 8 + import { z } from 'zod' 9 + import { nice_form } from '$lib/niceform' 10 + 11 + const schema = z.object({ 12 + name: z.string(), 13 + }) 14 + 15 + export const actions = { 16 + async default(event) { 17 + const form = await nice_form.zod(schema, event) 18 + if (!form.valid) { 19 + return form.fail(400) 20 + } 21 + if (form.data.name === 'Hi') { 22 + return form.set_error('name', 'You are a failure') 23 + } 24 + 25 + return { 26 + success: true, 27 + } 28 + }, 29 + } 30 + ``` 31 + 32 + ### Example Input wrapper component 33 + 34 + Includes type-safe `name` attribute, automatic error messages and label with automatic ID 35 + 36 + <img width="644" alt="image" src="https://github.com/user-attachments/assets/f1013bc2-5e61-4a50-b8c4-f3dafa54d3c3" /> 37 + 38 + 39 + ```svelte 40 + <script lang="ts" generics="F extends PartialNiceForm"> 41 + import type { HTMLInputAttributes } from 'svelte/elements' 42 + import { scale, slide } from 'svelte/transition' 43 + import { backOut } from 'svelte/easing' 44 + import { sequential_num, type AddFormProps, type PartialNiceForm } from './niceform' 45 + 46 + let { 47 + form, 48 + label, 49 + value = $bindable(), 50 + ...props 51 + }: AddFormProps<HTMLInputAttributes, F> = $props() 52 + 53 + let errors = $derived(form?.errors ?? {}) 54 + 55 + const id = 'input-' + sequential_num() 56 + </script> 57 + 58 + <div> 59 + {#if label} 60 + <label class="text-label mb-0.5 block text-sm" for={props.id ?? id}>{label}</label> 61 + {/if} 62 + <input class={['input', props['class']]} id={label ? id : undefined} bind:value {...props} /> 63 + {#if props.name && errors[props.name]} 64 + <span class="block origin-top-left" in:scale={{ duration: 250, easing: backOut }}> 65 + <span class="block text-sm text-red-500" transition:slide={{ duration: 100 }}> 66 + {errors[props.name]} 67 + </span> 68 + </span> 69 + {/if} 70 + </div> 71 + ```