Form validation is hard. That’s why there are several libraries that handle form validation for us, so we do not have to set up custom validation solutions ourselves. Every project has different form validation needs and there is no one-size-fits-all solution.
Therefore, in this article, I will walk you through the most popular and active Svelte form validation libraries to help you choose which one to use in your next project. I chose these seven libraries based on the number of GitHub stars and npm downloads they have, so you can be confident that the library you choose is popular among other devs.
The libraries are as follows:
Svelte forms lib is a Formik-inspired library for building forms easily in a Svelte project. While it does not come with many features, It handles the basic scenarios of validating forms and displaying errors well. Svelte forms lib is a good, light library to use when setting up basic form validation.
Run the command below in your terminal to install the library:
npm i svelte-forms-lib
The core of integrating Svelte forms lib into a form lies in the createForm
function, as seen here:
<script> import { createForm } from "svelte-forms-lib"; import * as yup from "yup"; const { form, errors, state, handleChange, handleSubmit } = createForm({ initialValues: { name: "", email: "" }, validationSchema: yup.object().shape({ name: yup.string().required(), email: yup.string().email().required() }), onSubmit: values => { alert(JSON.stringify(values)); } }); </script> <form on:submit={handleSubmit}> <input id="name" name="name" on:change={handleChange} on:blur={handleChange} bind:value={$form.name} placeholder="name" /> {#if $errors.name} <small>{$errors.name}</small> {/if} <input id="email" name="email" on:change={handleChange} on:blur={handleChange} bind:value={$form.email} placeholder="email" /> {#if $errors.email} <small>{$errors.email}</small> {/if} <button type="submit">submit</button> </form>
createForm
gives us access to useful form helps like handleChange
and handleSubmit
, among others. We will need these helper functions to set up the form.
Aside from helper functions, Svelte forms lib exposes observable values that give us information on the current state of the form. You can check out the list of available observables here.
We pass a config object as an argument to createForm
. Here, we define the initialValues
of the form and an onSubmit
handler that will handle the form submission. Having configured createForm
, we need to hook the profile form up to Svelte forms lib, so it can track the form values and handle the submission.
To do that, we pass the handleSubmit
helper to the form
element. We also pass handleChange
to the input fields and bind
their values to the form
observable.
Svelte forms lib supports validation with Yup through a validationSchema
prop, which takes in a schema object. Svelte forms lib also supports custom validation.
As a library inspired by Formik, Svelte forms lib has a similar API. A developer coming from a React background will find this library easy to work with.
Another developer experience plus is that, like Formik, Svelte forms lib provides custom components:
<script> import { Form, Field, ErrorMessage, Select } from "svelte-forms-lib"; import schema from "./schema"; const formProps = { initialValues: {}, validationSchema: schema, onSubmit: (values) => { alert(JSON.stringify(values)); }, }; </script> <div class="container"> <h1>Registration Form</h1> <Form {...formProps}> <div> <Field type="text" name="name" placeholder="Name" /> <ErrorMessage name="name" /> </div> <div> <Field type="email" name="email" placeholder="Email" /> <ErrorMessage name="email" /> </div> <button type="submit">Submit</button> </Form> </div>
It provides Form
, Field
, Select
, and ErrorMessage
components. Using these custom components will reduce the boilerplate and make the form code very concise. We no longer need to conditionally render the error for each field, because ErrorMessage
handles it for us.
Svelte forms lib has easy-to-understand and beginner-friendly documentation. The docs provide several examples that cover different use cases and code snippets that can easily be copied.
Felte is a simple form library for Svelte that aims to help make form management and validation easy. Felte is packed with features that cover several form handling and validation use cases. Due to the several integrations available with Felte, it can be overwhelming to work with. Hence, I advise you use it only for complex scenarios like multistep forms.
Run the command below in your terminal to install the library:
npm i felte
Felte provides a createForm
function that we can use to set up forms like so:
<script> import { createForm } from "felte"; import { validator } from "@felte/validator-yup"; import * as yup from "yup"; const schema = yup.object({ email: yup.string().email().required(), name: yup.string().required(), }); const { form, errors } = createForm({ extend: validator, validateSchema: schema, onSubmit: async (values) => { alert(JSON.stringify(values)); }, }); </script> <form use:form on:submit|preventDefault> <input type="text" name="name" /> {#if $errors.name} <span class="error">{$errors.name}</span> {/if} <input type="email" name="email" /> {#if $errors.email} <span class="error">{$errors.email}</span> {/if} <button type="submit">Submit</button> </form>
From createForm
, we pull out a form
action that we pass to HTML’s form
element through Svelte’s use
directive. This is all you need to integrate Felte into your forms and make them form reactive.
createForm
accepts a config object where we set up validation with Yup, and define an onSubmit
function that handles the form submission.
With Felte, you can spin up your own custom validation or use libraries like Yup, Zod, or Superstruct.
In the code snippet above, we used Yup. We access the errors
object from createForm
and conditionally display the error related to each input field.
Felte is a beginner-friendly library full of plenty of features and options. I love the fact that it supports validation with Yup, though we have to install a third party library, @felte/validator-yup
, to set it up.
Felte has extremely detailed, organized, and easy-to-understand documentation filled with demos and code snippets that cover several use cases.
Svelte Use Form is an easy-to-use form library that handles the validation and state of each input field, and handles basic form validation and integration well. However, it does not provide out-of-the-box handling for advanced cases like multistep forms. It supports inputs, textarea, selects, radio buttons, and checkboxes.
Run the command below in your terminal to install the library:
npm i -D svelte-use-form
Svelte Use Form provides a useForm
function we can hook to HTML’s form
element through Svelte’s use
directive:
<script> import {useForm, Hint, HintGroup, validators, minLength,email,required} from "svelte-use-form"; const form = useForm(); let formData = {}; //we store the form values here const onSubmit = () => { $form.touched = true; if ($form.valid) { alert(JSON.stringify(formData)); } }; </script> <form use:form> <div class="form-row"> <label for="name">Name</label> <input type="name" name="name" bind:value={formData.name} use:validators={[required, minLength(5)]} /> <HintGroup for="name"> <Hint on="required">Name is required</Hint> <Hint on="minLength" hideWhenRequired let:value> Name requires at least {value} characters.</Hint > </HintGroup> </div> <div class="form-row"> <label for="email">Email</label> <input type="email" name="email" use:validators={[required, email]} bind:value={formData.email} /> <HintGroup for="email"> <Hint on="required">Email is required</Hint> <Hint on="email" hideWhenRequired>Email is not valid</Hint> </HintGroup> </div> <button type="submit" on:click|preventDefault={onSubmit}>Sign In</button> </form>
One thing I love about using Svelte Use Form is how easy it is to integrate with forms. We can import useForm
, Hint
, HintGroup
, validators
, minLength
, email
, and required
.
useForm
is used in registering the form with Svelte Use Form. Hint
and HintGroup
are used to display the validation errors for each field. minLength
, email
, and required
are the validation checks we pass to validators
.
Svelte Use Form exports a validators
function that we can use to add validation to the input fields. We link validators
to the input fields using the use
directive.
For the name
input, we set it to required
, and its minLength
to five characters. For the email
input, we set it to required
to check that the email must be valid.
Svelte Use Form does not provide a submit
handler that can be used to handle form submission. Also, there is no values
object or something similar where the form values are stored, so we have to bind the values of the input fields to the formData
object.
As I write this article, there is no way to style error messages when using Hint
or HintGroup
. If we wanted to style the error messages, we will have to do so this way:
{#if $form.title?.touched && $form.title?.errors.minLength} <span class="error">The title requires at least {$form.title.errors.minLength} characters.</span> {/if}
Svelte Use Form has solid, clear documentation. Some demos are provided that show how the library works with different types of input fields, which makes Svelte Use Form easier to work with.
Svelte Final Form is a Svelte wrapper for Final Form, a framework-agnostic form library.
Run the command below in your terminal to install the library:
npm i --save final-form svelte-final-form
Svelte Final Form has a similar API to React Final Form. If you’re familiar with that, you will find this library easy to work with:
<script> import { Form, Field } from "svelte-final-form"; const initialValues = { name: "Nefe", email: "[email protected]", }; const onSubmit = (values) => { alert(JSON.stringify(values)); }; const validate = (values) => { const errors = {}; if (!values.name) { errors.name = "Name is required"; } if (!values.email) { errors.email = "Email is Required"; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(values.email)) { errors.email = "Invalid emaill address"; } return errors; }; </script> <Form {onSubmit} {validate} {initialValues} let:form let:state> <form on:submit|preventDefault={form.submit}> <Field name="name" let:input let:meta> <label for="name">Name</label> <input name={input.name} on:blur={input.onBlur} on:focus={input.onFocus} on:input={(e) => input.onChange(e.target.value)} type="text" value={input.value} /> {#if meta.touched && meta.error} <span class="error">{meta.error}</span> {/if} </Field> <Field name="email" let:input let:meta> <label for="email">Name</label> <input name={input.email} on:blur={input.onBlur} on:focus={input.onFocus} on:input={(e) => input.onChange(e.target.value)} type="text" value={input.value} /> {#if meta.touched && meta.error} <span class="error">{meta.error}</span> {/if} </Field> <button type="submit" disabled={state.submitting}>Submit</button> </form> </Form>
The Form
component is a special wrapper provided by Svelte Final Form that manages the state of the form. Form
passes the form
and state
components to its children through the let
directive.
Similar to Form
, Field
passes input
and meta
components to its input field children.
input
contains the necessary methods like onBlur
, onFocus
, and onChange
that we need to pass to the input fields.
The meta
object contains information on the state of the form. We determine whether the inputs have been touched or if they have errors from meta
.
Svelte Final Form does not support validation with Yup or other object validation schemas, so we have to create a custom validation ourselves.
The validate
function handles the validation for the form. The onSubmit
function will be called with the values of your form when the user submits the form and all validation passes.
Svelte Final Form makes form validation awesome and fun. Not only does it “just work,” but it makes it easy to understand how the code works.
It has a beginner-friendly API, and as far as form submission goes, Form
has an onSubmit
prop that takes in a submit function. We don’t have to track the form data, because Svelte Final Form handles that for us.
Svelte Final Form does not have an in-depth documentation library because it does not need one; it is easy to understand. However, it would be awesome if more demos were made available.
Svelte-yup is a Svelte component library used to validate forms with Yup. While svelte-yup supports form validation with Yup, you will have to create the validation integration, unlike other libraries that handle it for you. Having a deeper knowledge of Yup may be needed for svelte-yup to be fully maximized.
Run the command below in your terminal to install the library:
npm i svelte-yup yup
Svelte-yup provides Form
and Message
components we can use to integrate it into our forms:
<script> import * as yup from 'yup'; import {Form, Message} from 'svelte-yup'; let schema = yup.object().shape({ name: yup.string().required().max(30).label("Name"), email: yup.string().required().email().label("Email address"), }); let fields = {name: "", email: ""}; let submitted = false; let isValid; function formSubmit(){ submitted = true; isValid = schema.isValidSync(fields); if(isValid){ alert(JSON.stringify(fields)); } } </script> <Form {schema} {fields} submitHandler={formSubmit} {submitted}> <input type="text" bind:value={fields.name} placeholder="Name"> <Message name="name" /> <input type="text" bind:value={fields.email} placeholder="Email address"> <Message name="email" /> <button type="submit">Submit</button> </Form>
Svelte-yup relies on Yup to handle form validation. When formSubmit
is called, we set submitted
to true
. However, the core validation takes place in schema.isValidSync(fields)
. We store the result of this validation check in the isValid
variable, and if it is valid, we submit the form data.
There is no built-in way to check the form and validation states, so we have to set up submitted
and isValid
variables for them.
Svelte-yup comes with Form and Message
components, and Message
handles displaying the form errors for us, a plus for the developer experience.
Because svelte-yup handles validation with Yup, people familiar with Yup don’t need to learn a new validation syntax. This makes it easy to work with.
The documentation for svelte-yup is well-structured and detailed. The docs provide demos and even show how to use it with Material UI and Bootstrap custom form fields.
Similar to Svelte forms lib, Sveltik is also a Formik-inspired library for handling forms in Svelte. Being a Formik-inspired library, you can learn possible ways Sveltik has been used based on how Formik was used. You can use the Formik examples as guides on how to integrate Sveltik into your app.
Run the command below in your terminal to install the library:
npm i sveltik
Sveltik comes with Sveltik
, Form
, Field
and ErrorMessage
custom components, which we can use in setting up forms like so:
<script> import { Sveltik, Form, Field, ErrorMessage } from 'sveltik' let initialValues = { name: '', email: '', } let validate = values => { const errors = {} if(!values.name){ errors.name = "Name is required" } if (!values.email) { errors.email = 'Email is required' } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) { errors.email = 'Invalid email address' } return errors } let onSubmit = (values) => { alert(JSON.stringify(values)) } </script> <Sveltik {initialValues} {validate} {onSubmit}> <Form> <div class="form-row"> <Field type="text" name="name" /> <ErrorMessage name="name" as="span" /> </div> <div class="form-row"> <Field type="email" name="email" /> <ErrorMessage name="email" as="span" /> </div> <button type="submit">Submit</button> </Form> </Sveltik>
In the Sveltik
component, we pass in initialValues
, validate
, and onSubmit
props.
initialValues
is an object that holds the initial values of the respective form fields, validate
accepts a function that handles the form validation, and onSumbit
takes a function that handles the form submission. This runs only when there are no errors present in the form fields.
Form
is a small wrapper around an HTML <form>
element that automatically hooks into Sveltik’s handleSubmit
and handleReset
. ErrorMessage
renders the error message of a given field if that field has been visited and there is an error.
Field
automatically links the input’s onChange
, onBlur
, and value
attributes to Formik’s handleChange
, handleBlur
, and values
object, respectively. It uses the name
prop to match up with the state and automatically keeps the state in sync with the input value. It renders an HTML input field by default.
Sveltik does not provide out-of-the-box Yup integration like Svelte forms lib does with its validationSchema
prop. This means we have to create custom validation ourselves, like in the code snippet above.
In the validate
function, we run validation checks for the name
and email
input fields, and based on the error, update the errors
object accordingly.
Because Sveltik is a Formik-inspired library, anyone who has experience using Formik will find it easy to work with. The Field
and ErrorMessage
components abstract the repetitive boilerplate code like setting up onBlur
, onChange
, and tracking the value for each field.
Not only does this make Sveltik a beginner-friendly library, but also one that provides a great developer experience.
Sveltik has an easy-to-understand documentation. However, it would be nice to see more demos that cover different scenarios.
With sveltejs-forms, we can make declarative forms in Svelte. It provides Input
, Select
, and Choice
to make integration easier. You won’t need to set up onChange
, onBlur
, and other form event handlers because the components abstract those handlers.
Run the command below in your terminal to install the library:
npm i sveltejs-forms
I love how straightforward working with sveltejs-forms is. I can tell that a lot of thought was put into developing this library; it provides custom form, input, select, and checkbox components we can use to set up forms:
<script> import { Form, Input } from "sveltejs-forms"; import * as yup from "yup"; function handleSubmit({ detail: { values, setSubmitting, resetForm } }) { alert(JSON.stringify(values)); setSubmitting(false); resetForm({ name: "", email: "" }); } let schema = yup.object().shape({ name: yup.string().required().label("Name"), email: yup.string().required().email().label("Email address"), }); </script> <Form {schema} validateOnBlur={false} validateOnChange={false} on:submit={handleSubmit} > <Input name="name" type="text" label="Name" placeholder="Name" /> <Input name="email" label="Email Address" placeholder="Email" /> <button type="submit">Submit</button> </Form>
Here, we set up the input fields by passing in the necessary name
and type
props to the Input
component. The Form
component accepts validateOnBlur
and validateOnChange
props where we define when the validation should run.
We set up a handleSubmit
function that we pass to the Form
‘s on:submit
event. That’s all it takes to set up a basic integration!
Sveltejs-forms supports validation with Yup. Form
has a schema
prop, where we pass the validation schema we define for the input fields. The name for each schema we define must correspond to each input field’s name attribute. With that, Form
tracks the validity and errors of each field.
What about displaying errors? The Form
and Input
components handle that for us. Form
doesn’t just track the validity and errors of each field, it also creates a context where an errors
object is stored. The Input
component accesses that errors
object, and conditionally displays any error that exists in a given field.
The fact that sveltejs-forms provides custom components that abstract dealing with things like on:change
, on:blur
, on:input
, and setting the value of inputs for us is a huge developer experience plus. This makes setting up forms not only easy, but fast. The form data is tracked and stored for us, so we don’t have to bind the inputs and store the data ourselves.
We do, however, have to manually reset the input fields. If we had 15 inputs, that would be repetitive and tedious. It would be nice if there was a resetForm
method, or something similar, that can be called to reset the input fields for us.
Sveltejs-forms has a straightforward documentation. It is brief because it’s a straightforward library that is easy to get started with. It also covers how to work with custom components.
GitHub stars | Weekly npm downloads | Minified + Gzipped bundle size | Yup integration | Documentation | |
---|---|---|---|---|---|
Svelte forms lib | 331 | 1,148 | 5.2kb | Yes | Great |
Felte | 158 | 771 | 4kb | Yes | Great |
Svelte Use Form | 91 | 878 | 3.5kb | No | Good |
Svelte Final Form | 32 | 131 | 5.6kb | No | Basic |
svelte-yup | 18 | 81 | 4.1kb | Yes | Great |
Sveltik | 165 | 50 | 14.4kb | No | Good |
sveltejs-forms | 179 | 351 | 8kb | Yes | Good |
In this article, we covered the top form validation libraries in Svelte. So far, Svelte forms lib has met my form handling and validation needs, and I always use it when I can.
At the end of the day, each library is great in its own way. When deciding which library to use in the future, check the metrics we discussed and weigh them against the goals and requirements of your app.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.