How to Validate Form in Svelte: Simple and Effective Methods
In Svelte, you validate a form by binding input values with
bind:value and using reactive statements or event handlers to check input validity. You can show error messages conditionally and prevent form submission if validation fails.Syntax
Use bind:value to connect input fields to variables. Use reactive statements ($:) to watch and validate these variables. Use event handlers like on:submit to control form submission.
bind:value: keeps input and variable in sync.$:reactive statement: runs code when dependencies change.on:submit|preventDefault: handles form submit and stops default page reload.
svelte
<form on:submit|preventDefault={handleSubmit}>
<input type="text" bind:value={name} />
{#if nameError}
<p>{nameError}</p>
{/if}
<button type="submit">Submit</button>
</form>
<script>
let name = '';
let nameError = '';
$: nameError = name.trim() === '' ? 'Name is required' : '';
function handleSubmit() {
if (!nameError) {
alert('Form submitted with name: ' + name);
}
}
</script>Output
A form with a text input and a submit button. If the input is empty, an error message 'Name is required' appears below the input. On valid input, submitting shows an alert with the entered name.
Example
This example shows a simple form with name and email fields. It validates that both fields are not empty and that the email looks like an email. Errors show below each input. The form only submits if all validations pass.
svelte
<form on:submit|preventDefault={handleSubmit}>
<label for="name">Name:</label>
<input id="name" type="text" bind:value={name} aria-describedby="nameError" />
{#if nameError}
<p id="nameError" style="color: red;">{nameError}</p>
{/if}
<label for="email">Email:</label>
<input id="email" type="email" bind:value={email} aria-describedby="emailError" />
{#if emailError}
<p id="emailError" style="color: red;">{emailError}</p>
{/if}
<button type="submit">Submit</button>
</form>
<script>
let name = '';
let email = '';
let nameError = '';
let emailError = '';
$: nameError = name.trim() === '' ? 'Name is required' : '';
$: emailError = email.trim() === '' ? 'Email is required' : !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email) ? 'Valid email is required' : '';
function handleSubmit() {
if (!nameError && !emailError) {
alert(`Form submitted with Name: ${name} and Email: ${email}`);
}
}
</script>Output
A form with two inputs labeled Name and Email. If either is empty or invalid, red error messages appear below them. On valid input, submitting shows an alert with the entered name and email.
Common Pitfalls
- Not preventing default form submission causes page reload, losing state.
- Not trimming input can cause false validation failures.
- Using synchronous validation only on submit misses live feedback.
- Not associating error messages with inputs via
aria-describedbyhurts accessibility.
svelte
<!-- Wrong: No preventDefault, no trimming -->
<form on:submit={submit}>
<input bind:value={name} />
<button type="submit">Submit</button>
</form>
<script>
let name = '';
function submit(event) {
if (name === '') {
alert('Name required');
}
}
</script>
<!-- Right: preventDefault and trim input -->
<form on:submit|preventDefault={submit}>
<input bind:value={name} />
<button type="submit">Submit</button>
</form>
<script>
let name = '';
function submit() {
if (name.trim() === '') {
alert('Name required');
}
}
</script>Quick Reference
- bind:value: Connect input to variable.
- $: Reactive statement for validation logic.
- on:submit|preventDefault: Handle form submit without page reload.
- aria-describedby: Link error messages for accessibility.
- Trim inputs before validating to avoid whitespace errors.
Key Takeaways
Use bind:value to keep form inputs and variables in sync.
Validate inputs reactively with $: statements for live feedback.
Prevent default form submission to control validation and submission flow.
Show error messages conditionally and link them with aria-describedby for accessibility.
Always trim input values before validating to avoid false errors.