npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

svelte-valibot-form

v0.0.5

Published

A Svelte form validation library using Valibot.

Downloads

276

Readme

Valibot SvelteKit Form

This is a validation library for SvelteKit, integrating Valibot to simplify validation on both front and backend. This library provides reusable form components, context-aware validation, and error handling.

Table of Contents


Installation

Install the library using npm:

npm install svelte-valibot-form

Make sure to install its dependencies:

npm install valibot

Usage

Form Setup

To create a form that validates data based on a schema, import ValibotForm and pass the necessary schema. Here’s a basic login form example:

<!-- +page.svelte -->
<script lang="ts">
	import FileInput from '$lib/components/FileInput.svelte';
	import GenericInput from '$lib/components/GenericInput.svelte';
	import ValibotForm from '$lib/components/ValibotForm.svelte';
	import { ValibotAction } from '$lib/index.js';
	import { LoginSchema, type LoginSchemaType } from '$lib/schema/LoginSchema.js';
	import type { InferOutput } from 'valibot';

	const login = async (data: InferOutput<LoginSchemaType>) => await ValibotAction.call('login', LoginSchema, data);
</script>

<ValibotForm
	schema={LoginSchema}
	defaultValues={{ email: '', password: 'teste', file: [new File([], 'test.png')] }}
	onSubmit={login}
	onError={console.log}
>
	<GenericInput name="email" type="email" placeholder="Email" />
	<GenericInput name="password" type="password" placeholder="Password" />
	<FileInput name="file" multiple />
	<button type="submit">Login</button>
</ValibotForm>

Custom Inputs

To access validation errors and default values directly within your form elements, use getContext to retrieve the validation context.

Form Input Example

<script lang="ts">
	import { getContext } from 'svelte';
	import type { LoginSchemaType } from '$lib/schema/LoginSchema.js';
	import type { ValibotErrorContext, ValibotErrorKey } from '$lib/types.js';

	const props: SvelteHTMLElements['input'] = $props();
	const ctx = getContext<ValibotErrorContext<LoginSchemaType>>('form');
	const key = props.name as ValibotErrorKey<LoginSchemaType>;

	const defaultValue = ctx?.defaultValues?.[key];
	const error = ctx?.errors?.[key];

	let files: FileList | null = $state(null);

	$effect(() => {
		if (defaultValue) {
			const dt = new DataTransfer();
			Array.isArray(defaultValue) ? defaultValue.forEach((file) => dt.items.add(file)) : dt.items.add(defaultValue);
			files = dt.files;
		}
	});
</script>

<div>
	<input type="file" bind:files {...props} />
	{#if error}
		<p>{error}</p>
	{/if}
</div>

Normal Input Example

<script lang="ts">
	import { getContext } from 'svelte';
	import type { SvelteHTMLElements } from 'svelte/elements';
	const props: SvelteHTMLElements['input'] = $props();
	import type { LoginSchemaType } from '$lib/schema/LoginSchema.js';
	import type { ValibotErrorContext, ValibotErrorKey } from '$lib/types.js';

	const key = props.name as ValibotErrorKey<LoginSchemaType>;
	const ctx = getContext<ValibotErrorContext<LoginSchemaType>>('form');

	const value = ctx?.defaultValues?.[key];
	const error = $derived(ctx?.errors?.[key]);
</script>

<div>
	<input {value} {...props} />
	{#if error}
		<p>{error}</p>
	{/if}
</div>

Server Actions

On the server side, simply parse incoming form data using the ValibotAction wrapper function with the schema to validate the data. The return object of the Action will have a new member called data that has all the submitted data.

// +page.server.ts
import { withValibot } from '$lib/request/WithSchema.js';
import { LoginSchema } from '$lib/schema/LoginSchema.js';
import type { Actions } from './$types.js';

export const actions: Actions = {
	login: withValibot(LoginSchema, async ({ data, request }) => {
		console.log(request);
		console.log(data);
	})
};

API Reference

ValibotForm Props

The ValibotForm component accepts the following props:

type ValibotFormProps = SvelteHTMLElements['form'] & {
	schema: Schema;
	forceSubmit?: boolean;
	defaultValues?: Partial<v.InferInput<Schema>>;
	onSubmit?: (values: v.InferOutput<Schema>) => void;
	onError?: (errors: [v.InferIssue<Schema>, ...v.InferIssue<Schema>[]]) => void;
};
  • schema (required): Validation schema based on Valibot.
  • forceSubmit: (optional) Forces form submission when set to true, will be automatically set to false after use.
  • defaultValues: (optional) Set initial values for the form fields.
  • onSubmit: Callback function invoked when form validation is successful.
  • onError: Callback function invoked with validation errors.

Context Access

Each form element can access validation context properties such as defaultValues and errors using getContext.

const ctx = getContext<ValibotErrorContext<LoginSchemaType>>('form');
  • defaultValues: Access default values set in the form.
  • errors: Access validation errors associated with each form field.

Example

Here’s a complete example to illustrate the library’s usage.

<script lang="ts">
	import ValibotForm from '$lib/components/ValibotForm.svelte';
	import GenericInput from '$lib/components/GenericInput.svelte';
	import { LoginSchema, type LoginSchemaType } from '$lib/schema/LoginSchema.js';
	import { ValibotAction } from '$lib/index.js';
	import type { InferOutput } from 'valibot';

	const login = async (data: InferOutput<LoginSchemaType>) => await ValibotAction.call('login', LoginSchema, data);
</script>

<ValibotForm schema={LoginSchema} defaultValues={{ email: '', password: '' }} onSubmit={login} onError={console.error}>
	<GenericInput name="email" type="email" placeholder="Email" />
	<GenericInput name="password" type="password" placeholder="Password" />
	<button type="submit">Login</button>
</ValibotForm>

ValibotAction

The ValibotAction class is a utility for submitting validated form data directly to server actions in SvelteKit. It allows for seamless form submission, including handling file uploads, transforming the form data, and validating inputs against a Valibot schema before sending to the server.

How It Works

ValibotAction.call validates the input data with the provided Valibot schema. If validation succeeds, it converts the data into FormData, handling nested objects and file uploads. Then, it sends the data to the specified server action endpoint. If the invalidate option is set, the cache will be invalidated after a successful submission.

Usage

In a form component, ValibotAction.call can be used to validate and send form data:

import { ValibotAction } from '$lib/index.js';
import { LoginSchema, type LoginSchemaType } from '$lib/schema/LoginSchema.js';
import type { InferOutput } from 'valibot';

const login = async (data: InferOutput<LoginSchemaType>) => await ValibotAction.call('login', LoginSchema, data);

API

ValibotAction.call

static async call<Schema extends GenericValibotObject>(
  action: string,
  schema: Schema,
  data: InferInput<Schema>,
  options?: ActionOptions
): Promise<{ success: boolean; errors?: Record<string, string>; issues?: ValibotIssue[] }>
  • action (string): Name of the server action to invoke.

  • schema (GenericValibotObject): A Valibot schema defining validation rules for the data.

  • data (InferInput): Input data to validate and send to the server action.

  • options (ActionOptions, optional): Additional options, including:

    • invalidate (boolean): If true, invalidates the client-side cache after successful submission. Defaults to true.
  • Returns: An object containing:

    • success (boolean): Indicates if the validation and submission were successful.
    • errors (optional): An error map generated if validation fails.
    • issues (optional): Array of Valibot validation issues if validation fails.

License

This project is licensed under the MIT License.


This README provides a structured overview of your Valibot SvelteKit library, detailing the setup and usage of key components, properties, and context, with example code snippets. Let me know if you'd like further customization!