Last active
July 15, 2023 06:03
-
-
Save jaysson/08bc5f8a9d7200fc3dc72c8e983c240c to your computer and use it in GitHub Desktop.
Realtime validation in sveltekit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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