In order to implement a loading indicator in a SvelteKit form using use:enhance
Form Actions, you need to customize use:enhance.
The basic idea is:
- Create a
sending
boolean variable that represents whether the form is submitting or not - Customize use enhance and set
sending
totrue
when the form starts loading, and then tofalse
when the form finishes.
Let’s look at an example of a component where you send in your name and it returns back “Hello ${name}!”.
<script>
import { enhance } from "$app/forms";
import { invalidateAll } from "$app/navigation";
export let form;
let sending = false;
</script>
<h1>Greeter</h1>
{#if sending}
<p>
Sending...
</p>
{:else if form}
<p>{form?.greeting}</p>
{:else}
<p>What's your name?</p>
{/if}
<form
method="POST"
use:enhance={() => {
sending = true;
return ({ update }) => {
// Set invalidateAll to false if you don't want to reload page data when submitting
update({ invalidateAll: true }).finally(async () => {
sending = false;
});
};
}}
>
<input disabled={sending} type="text" name="name" autofocus />
<button disabled={sending} type="submit">Submit</button>
</form>
And here is the Form Action:
import type { Actions } from './$types';
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const text = data.get('name');
await new Promise((resolve) => setTimeout(resolve, 3000));
return {
greeting: `Hello ${text}!`,
}
},
} satisfies Actions;
Some CSS was ommitted. With this component, we get the below effect. You can also check out the live demo here!