Skip to content

Instantly share code, notes, and snippets.

@jaysson
Last active July 15, 2023 06:03
Show Gist options
  • Save jaysson/08bc5f8a9d7200fc3dc72c8e983c240c to your computer and use it in GitHub Desktop.
Save jaysson/08bc5f8a9d7200fc3dc72c8e983c240c to your computer and use it in GitHub Desktop.
Realtime validation in sveltekit
import { deserialize, applyAction } from '$app/forms';
import debounce from 'debounce';
/**
* After the first submission, asynchronously submits the form after new input
* The page action should return `fail(422, {data, errors}) when validation fails
* The actions should return a `fail(204, {data})` WITHOUT actually processing the form submission when `x-precognition` header is present and validation succeeds.
* Use it in your form: `<form method="post" use:validation>`
* @param form The form element on which the use directive is applied
*/
export default function validation(form: HTMLFormElement) {
let shouldValidate = false;
let controller: AbortController | null = null;
async function callAction(headers: Record<string, string>) {
controller?.abort();
controller = new AbortController();
const data = new FormData(form);
const response = await fetch(form.action, {
method: form.method,
body: data,
headers,
signal: controller.signal
});
const result = deserialize(await response.text());
return applyAction(result);
}
const handleChange = debounce(function () {
if (!shouldValidate) return;
return callAction({
'x-sveltekit-action': 'true',
'x-precognition': 'true'
});
}, 500);
async function handleSubmit(e: SubmitEvent) {
e.preventDefault();
await callAction({
'x-sveltekit-action': 'true'
});
shouldValidate = true;
}
form.addEventListener('submit', handleSubmit);
form.addEventListener('input', handleChange);
return {
destroy() {
form.removeEventListener('input', handleChange);
form.removeEventListener('submit', handleSubmit);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment