SvelteKit form actions are the bomb

- Posted in svelte webdev

In the video above I demonstrate a little app and its code in a slightly unorderly fashion, so I thought I’d put some words down and hopefully make things more clear.

First of all, this is just a demo app and not a real-life application, although it contains concepts that a real-life application will need like environment variables, progressive enhancement, data fetching, calling an API etc.

I re-architected an earlier version of this todo app to use the latest changes in SvelteKit. The old version used fetch calls all over the place and was hardly optimized. I made it a few months ago to practice with HTTP verbs like PATCH, PUT, DELETE etc.

This new version works way better, and behind the scenes it’s using the latest SvelteKit logic. This means using +page.js+page.server.js, the new load function etc.

These todo demos might seem silly but serve the purpose of showing how a real-world app could look like in the fewest lines of code. They’re a way to practice and evaluate the concepts behind something.

In the case of the Sveltekit todo app (I mean the official one, which you can see by generating a new SvelteKit project), an API is called, and you can add, edit and delete todo items.

In my demo app, there is similar functionality, although a Trello board is being used as a back-end.

The reason that I do this is so that this way I don’t need to build an API (a skill I currently don’t have) and I can (1) use their excellent documentation and (2) I can focus on the heart of the matter, which is building a working app where I can experiment with doing things that a real-world app should do i.e. all your CRUD-y goodness: add stuff, modify stuff, delete stuff.

Buuuut here I can do it in a way that is super modern. The gist of the techniques used is that you can have all the benefits of an MPA + SPA combined.

It’s quite hard to explain, because you’d have to piece together a few of Rich Harris’s Svelte/SvelteKit talks to really make sense of it. But I’ll give it a shot.

In one of them he had a progressively enhanced form demo. He disabled JS and his form still worked. Because everything ran on the server, and was only progressively enhanced by the client.

In his newest talk at the real-life Svelte Summit (which I just attended in Stockholm) he came up with another demo, this time implementing Sverdle, a Wordle clone in SvelteKit. The same logic applied here – fully running on the server, enhanced on the client.

If you ever read about Remix for React this will sound very familiar. SvelteKit is built using as much of the web platform as possible (we are talking FormData, actions inspired by HTTP verbs etc.).

I think all of this is very exciting and I couldn’t wait to try it out, so that’s what I did. You can watch the video for my full explanation.

I find the code logic behind this to be beautiful.

For example, the code belows shows a simplified delete button, tied to a form action. The first part of the code lives in the +page.js template, the other in the +page.server.js file.

  <form
    action="?/delete"
    method="POST"
    use:enhance={() => {
      return ({ form, result }) => {
        if (result.type === 'success') {
          deleted = true
        }
      };
    }}
  >
    <input type="hidden" name="id" value={data.id}>
    <button>Delete</button>
  </form>
export const actions = {
  delete: async ({ request, locals }) => {
    const form = await request.formData();
    await api('DELETE', 'cards/'+form.get('id'));
  }
}

You could make a small form for every CRUD action on the page (like in SvelteKit’s demo app) or work with bigger forms that do more.

I love this new approach of working in SvelteKit. It is so concise, yet it does so much. I believe SvelteKit form actions are the bomb and usher in the future of forms in web apps. No more controlled inputs. Hello server side rendering and progressive enhancement!

You can find the GitHub repo for this project here.

Leave a Reply

Your email address will not be published. Required fields are marked *