Status messages
A status message like “Form posted” can be displayed after submitting a form. The validation object contains a message
store used for this:
Usage
const { form, message } = superForm(data.form);
It is used to display the message on the client, like any other store:
{#if $message}
<div class="message">{$message}</div>
{/if}
However, we need to send it from the server first. Using the message
function makes this rather simple.
The message helper
import { message, superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';
export const actions = {
default: async ({ request }) => {
const form = await superValidate(request, zod(schema));
if (!form.valid) {
// Will return fail(400, { form }) since form isn't valid
return message(form, 'Invalid form');
}
if (form.data.email.includes('spam')) {
// Will also return fail, since status is >= 400
// form.valid will also be set to false.
return message(form, 'No spam please', {
status: 403
});
}
// Just returns { form } with the message (and status code 200).
return message(form, 'Valid form!');
}
};
You can return any type with the message, like an object, if you want to send more information than a string:
return message(form, { text: 'User created', id: newId })
See right below for how to make this data strongly typed.
Strongly typed message
The message is of type any
by default, but you can type it using the superValidate
type parameters:
import { type Infer, superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';
// Inferred schema type as first parameter, message type second
const form = await superValidate<Infer<typeof schema>, string>(event, zod(schema));
A string can be a bit limiting though; more realistically, there will be some kind of status for the form submission, so making a Message
type can be useful for consistency.
import { type Infer, superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';
type Message = { status: 'error' | 'success' | 'warning'; text: string };
const form = await superValidate<Infer<typeof schema>, Message>(event, zod(schema));
To simplify this even further, if you have the same type for all status messages across the project, you can add a Message
type to the App.Superforms
namespace in src/app.d.ts, and it will be automatically set, no need for generic type parameters:
src/app.d.ts
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface Platform {}
namespace Superforms {
type Message = {
type: 'error' | 'success', text: string
}
}
}
}
src/routes/+page.svelte
<script lang="ts">
let { data } = $props();
const { form, message } = superForm(data.form);
</script>
{#if $message}
<div
class:success={$message.status == 'success'}
class:error={$message.status == 'error'}
>
{$message.text}
</div>
{/if}
Though if you want to keep it simple with a string or the default any
, you can use $page.status
to style the message appropriately:
<script lang="ts">
import { page } from '$app/stores';
let { data } = $props();
const { form, message } = superForm(data.form);
</script>
{#if $message}
<div
class:success={$page.status == 200}
class:error={$page.status >= 400}
>
{$message}
</div>
{/if}
Using the message data programmatically
If you return data that you want to use programmatically instead of just displaying it, like in a toast message, you can do that in the onUpdate or onUpdated event:
return message(form, { status: 'success', text: 'All went well' });
const { form, enhance } = superForm(data.form, {
onUpdated({ form }) {
if (form.message) {
// Display the message using a toast library
toast(form.message.text, {
icon: form.message.status == 'success' ? '✅' : '❌'
});
}
}
});
The difference between the two events is that you can modify and cancel the update in onUpdate
, compared to onUpdated
, where the form data, errors, etc have already updated, making it best for non-store-related things like displaying a toast.
Limitations
Since there is no form data returned when redirecting, in that case the message will be lost. It’s quite common to redirect after a successful post, so the message
property isn’t a general solution for displaying status messages.
The library sveltekit-flash-message is a complete solution that works with redirects, however. It can be directly integrated into Superforms, documented here.