How To Use Data Returned By A Form Action in SvelteKit

No Comments
Published: 14.05.2023

Do you want to use the data that is returned by a form action in SvelteKit? In this post, we will learn exactly that in a short step-by-step example!

Example use case: Show modal on update Donut success

We will continue the example from the last post where we manipulated the form data before sending it to the action: here.

Take an online donut shop that allows the owner to edit the entries using a form. After the creation of the form, it is pretty easy to redirect the user to another page, e.g., a success page using throw redirect(303, path).

That is a good approach if we want to always redirect the user to a specific site, but in some cases, we just want to show a simple modal or toast notification that tells the user that the edit was successful.

Let’s have a look at the initial edit donut component on the front end (+page.svelte):

<script lang="ts">
    import { enhance } from '$app/forms';
    export let data;
</script>

<svelte:head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css">
</svelte:head>

<section class="container">
    <h1>Edit {data.donut.name}</h1>

    <form method="POST" action="?/update" use:enhance={({data: formData}) => {
        formData.append('id', data.donut.id);
    }}>
        <label for="name">Name</label>
        <input type="text" name="name" id="name" value="{data.donut.name}">

        <label for="price">Price</label>
        <input type="number" name="price" id="price" value="{data.donut.price}">

        <label for="description">Description</label>
        <textarea name="description" id="description">{data.donut.description}</textarea>

        <button type="submit">Save</button>
    </form>
</section>

And the initial server side form action (+page.server.ts):

Need help or want to share feedback? Join my discord community!

import type { Actions, PageServerLoad } from './$types';

export const actions: Actions = {
    update: async ({request}) => {
        const data = await request.formData();
        console.log(...data);
        
        
        // save the data to the database e.g. with pocketbase
        // const record = await pb.collection('donuts').update(data.get('id'), data);
    }
};

export const load: PageServerLoad = async ({ params }) => {
    // load the data from the database e.g. with pocketbase
    // const record = await pb.collection('donuts').get(params.id);
    // return { donut: record };
    return { donut: {
        id: "vanille-donut",
        name: "Vanille Donut",
        description: "A donut with vanilla flavor",
        price: 1,
    }};
}

In the next step, we will show a modal on a successful update! Therefore we have two methods. One is super simple based on the ActionData, and the second one is a bit more complex based on the use:enhance action.

Use the Data returned by a Form Action in SvelteKit (ActionData)

First, we will have a look at how we can use the ActionData to show a modal on success. For that, we first have to access the ActionData inside a variable and add the HTML code for the Modal:

KOFI Logo

If this guide is helpful to you and you like what I do, please support me with a coffee!

<script lang="ts">
    import { enhance } from '$app/forms';
    import type { ActionData } from './$types.js';
    export let data;
    export let form: ActionData;
    export let closed = false;
</script>
<!-- ... -->
    </form>

    <dialog open={form?.success && !closed}>
        <article>
          <header>
            <a href="#close" aria-label="Close" class="close" on:click={() => closed = true}></a>
            Success
          </header>
          <p>
            Donut with name "{form?.name}" successfully updated!
          </p>
        </article>
    </dialog>

Besides the front end, we also have to return some data in the action. For that, we will return an object including the keys success and name:

// ...
export const actions: Actions = {
    update: async ({request}) => {
        // ...
        return { name: data.get('name'), success: data.get('name') !== '' };
    }
};
// ...

When we now click on the save button again, we can see that the modal with a success message opens:

use data returned by form action: success modal

With that, we can easily use data returned by the action. For the full code, check this GitHub Repository in the actiondata branch.

Use the Data returned by a Form Action in SvelteKit (use:enhance)

We can also access the data returned by the form action using the use:enhance action (read more on it here). For that, we have to return a function from the SubmitFunction in which we can access the result set. So let’s do exactly that and the logic and HTML code for the modal:

<script lang="ts">
    import { enhance } from '$app/forms';
    export let data;
    export let action: undefined | { success: boolean, name: string};
    let closed = false;
</script>
<!-- ... -->
    <form method="POST" action="?/update" use:enhance={({data: formData}) => {
        formData.append('id', data.donut.id);

        return async ({result}) => {
            action = { success: result.status === 200, name: result.data.name };
        };
    }}>
<!-- ... -->
    </form>

    <dialog open={action?.success && !closed}>
        <article>
          <header>
            <a href="#close" aria-label="Close" class="close" on:click={() => closed = true}></a>
            Success
          </header>
          <p>
            Donut with name "{action?.name}" successfully updated!
          </p>
        </article>
    </dialog>

Besides the front end, we also have to return some data in the form action. For that, we will return an object including the keys success and name:

// ...
export const actions: Actions = {
    update: async ({request}) => {
        // ...
        return { name: data.get('name') };
    }
};
// ...

When we now click on the save button again, we can see that the modal with a success message opens:

use data returned by form action: success modal

With that, we can easily use data returned by the action. For the full code, check this GitHub Repository in the enhance branch.

Conclusion

After this quick guide, we can use the full power of the SvelteKit Form Actions because we can now easily use the data returned by the form action!

If you liked the post, consider subscribing to my newsletter, and if you have any other questions, feel free to join the discord or email me.

[convertkit form=2303042]

Discussion (0)