By default, forms cause full page reloads. use:enhance makes them work like SPAs while keeping the HTML form as a fallback.
Basic Enhancement
svelte<script> import { enhance } from '$app/forms'; </script> <form method="POST" use:enhance> <input name="email" type="email" /> <button>Subscribe</button> </form>
Now the form:
- Submits via fetch (no page reload)
- Automatically updates
formprop with response - Still works without JavaScript!
Customizing Behavior
svelte<script> import { enhance } from '$app/forms'; let isSubmitting = $state(false); </script> <form method="POST" use:enhance={() => { isSubmitting = true; return async ({ result, update }) => { isSubmitting = false; if (result.type === 'success') { // Custom success handling showToast('Saved!'); } // Call update() to run default behavior // (update form prop, invalidate data) await update(); }; }}> <button disabled={isSubmitting}> {isSubmitting ? 'Saving...' : 'Save'} </button> </form>
Result Types
javascriptreturn async ({ result }) => { switch (result.type) { case 'success': // Action returned data console.log(result.data); break; case 'failure': // Action returned fail() console.log(result.data); break; case 'redirect': // Action threw redirect() console.log(result.location); break; case 'error': // Action threw error() console.log(result.error); break; } };
Preventing Default Update
svelte<form method="POST" use:enhance={() => { return async ({ result }) => { // Don't call update() - handle everything manually if (result.type === 'redirect') { goto(result.location); } }; }}>
Reset Form Option
svelte<form method="POST" use:enhance={() => { return async ({ update }) => { await update({ reset: true }); // Reset form fields }; }}>