:: krowemoh

Saturday | 10 MAY 2025
Posts Links Other About Now

previous
next

Communicating in Svelte

2025-05-02
svelte

Svelte has a number of ways of communicating between the backend and the frontend.

Initial Page Load

The most basic way of communicating between a server and the client is by running the code in +page.server.js.

This file will always run on the server side before the page is loaded. The data returned by this page is in a data variable that can be used inside +page.svelte.

/src/routes/hello/+page.server.js:

export async function load({ locals }) {
    name: "Something",
    
    return {
        name
    }
}

You can do any filesystem or database access you need inside this file.

/src/routes/hello/+page.svelte

<script>
   export let data;
</script>

<h1>Hello, {data.name}</h1>

Form Actions

The next way of communicating in svelte is by using form actions. Form actions are a good way of getting user input but can also be used to simply pass data from the client side to the server.

Form actions are written in the +page.server.js but are outside the load statement. Instead there is a action object.

/src/routes/hello/+page.server.js

export async function load({ locals }) {
   ...
}

export const actions = {
    update: async ({ locals, request, params }) => {
        // update item
        return {
            success: true,
        }
    },
    delete: async ({locals, request, params }) => {
        // delete item
        redirect(303, `/`);
    }
}

Here we have an update and delete action. These are called in the frontend by setting the form action attribute to ?/update and ?/date.

/src/routes/hello/+page.svelte

<script>
   export let form
</script>

{#if form}
   {form.error}
{/if}

<form action="?/update" method="POST">
    <input type="text" name="name" />
    <div class="mt-4">
        <button type="submit">Submit</futton>
    </div>
</form>

<form action="?/delete" method="POST"> 
    <button type="submit">
        Delete
    </button>
</form>

Here we have two form elements that each have a specific form action.

We also have the form variable being populated so that if there are any issues in the form, we can return that information back to the frontend where it can be displayed.

Form Actions via Fetch

Form actions can also be triggered via fetch calls. Instead of using the

tag, we can do a javascript fetch where we build the FormData type manually.

When accessing a form action in a fetch, we need to use the deserialize function to get the data properly.

export const actions = {
    upload: async ({ locals, request }) => {
        const formData = await request.formData();
        
        return {
            success: true,
        }
    },
}

The front will then be:

<script>
    import { enhance, deserialize } from '$app/forms';
    
    async function upload() {
        let formData = new FormData(uploadForm);
        
        let response = await fetch("?/upload", {
            method: 'POST',
            body: formData
        })
        
        response = deserialize(await response.text());
        
        if (!response.data.success) {
            alert(response.data.error);
            return;
        }
    }
<script>

Here we manually create the FormData and send it via fetch. We then get the response and deserialize it to use it.

Server Endpoints

You can also have communication through server endpoints. These are functions written in +server.js.

These endpoints are accessed via the fetch function in the frontend.

/src/routes/hello/+server.js

import { json, error } from '@sveltejs/kit';

export const POST = async ({ locals, request }) => {
    const reqData = await request.json();
    
    console.log(reqData);
    
    const response = {
        name: "John"
    };
    
    return json(response);
};

This endpoint can be accessed by doing a post request to /name.

In the frontend this will look like:

/src/routes/hello/+page.svelte

<script>
   let name = "";
   
   
    async function getName() {
        let response = await fetch("/name", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ something: "example", }),
        });
        
        response = await response.json();
        
        name = response.name;
    }
    
   getName();
</script>

<h1>Hello, {name}</h1>

Here we have a getName function that will retrieve the name passing in an empty object to the endpoint.

Once the name arrives, it will then get set and we should see our page update with the name.

You can use a similar fetch command to access form actions as well.

The community seems to use form actions for most things while using server endpoints more sparingly for generic requests.