Skip to content

Svelte Form Submission

Submit forms in your Svelte application seamlessly using Svelte 5 state management and standard asynchronous fetch().

Here is a form component utilizing Svelte 5’s $state runes and $props() to accept the Formkove endpoint and manage submission state:

<script lang="ts">
let { apiUrl }: { apiUrl: string } = $props();
let name = $state('');
let email = $state('');
let message = $state('');
let status: 'idle' | 'sending' | 'success' | 'error' = $state('idle');
let errorText = $state('');
async function handleSubmit(e: Event) {
e.preventDefault();
status = 'sending';
errorText = '';
try {
const res = await fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({ name, email, message }),
});
const json = await res.json();
if (res.ok) {
status = 'success';
name = '';
email = '';
message = '';
} else {
status = 'error';
errorText = json.error || 'Something went wrong.';
}
} catch {
status = 'error';
errorText = 'Network error. Please try again.';
}
}
</script>
<form onsubmit={handleSubmit} class="space-y-4">
<div>
<label for="svelte-name">Name</label>
<input id="svelte-name" bind:value={name} type="text" required />
</div>
<div>
<label for="svelte-email">Email</label>
<input id="svelte-email" bind:value={email} type="email" required />
</div>
<div>
<label for="svelte-message">Message</label>
<textarea id="svelte-message" bind:value={message} required></textarea>
</div>
<button type="submit" disabled={status === 'sending'}>
{status === 'sending' ? 'Sending...' : 'Send Message'}
</button>
{#if status === 'success'}
<p class="text-green-600">Message sent successfully!</p>
{:else if status === 'error'}
<p class="text-red-600">{errorText}</p>
{/if}
</form>
  • Retrieve response status (201 Created on success).
  • Use JSON.stringify to serialize input values from $state.
  • Disable the submit button during the request to prevent double-submissions.