From 6f8dd91157374d54090177eef2a8baf0750b4123 Mon Sep 17 00:00:00 2001 From: neeraj Date: Mon, 12 Feb 2024 12:16:36 +0530 Subject: [PATCH] form submit handler --- blocks/form/form.js | 5 +++ blocks/form/submit.js | 71 ++++++++++++++++++++++++++++++++++++++----- blocks/form/util.js | 4 --- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/blocks/form/form.js b/blocks/form/form.js index 5cf15822..310661c1 100644 --- a/blocks/form/form.js +++ b/blocks/form/form.js @@ -9,6 +9,7 @@ import GoogleReCaptcha from './integrations/recaptcha.js'; import fileDecorate from './file.js'; import DocBaseFormToAF from './transform.js'; +import handleSubmit from './submit.js'; export const DELAY_MS = 0; let captchaField; @@ -352,6 +353,10 @@ export async function createForm(formDef, data) { }, DELAY_MS); } + form.addEventListener('submit', (event) => { + handleSubmit(event, form); + }); + return form; } diff --git a/blocks/form/submit.js b/blocks/form/submit.js index 9fc83ee5..a513491f 100644 --- a/blocks/form/submit.js +++ b/blocks/form/submit.js @@ -1,25 +1,25 @@ import { checkValidation } from './util.js'; -export function submitSuccess(e, form) { +function submitSuccess(e, form) { const { payload } = e; - if (payload.body.redirectUrl) { + if (payload?.body?.redirectUrl) { window.location.assign(encodeURI(payload.body.redirectUrl)); - } else if (payload.body.thankYouMessage) { + } else { let thankYouMessage = form.querySelector('.form-message.success-message'); if (!thankYouMessage) { thankYouMessage = document.createElement('div'); thankYouMessage.className = 'form-message success-message'; } - thankYouMessage.innerHTML = payload.body.thankYouMessage; + thankYouMessage.innerHTML = 'Thanks for your submission'; form.prepend(thankYouMessage); if (thankYouMessage.scrollIntoView) { thankYouMessage.scrollIntoView({ behavior: 'smooth' }); } - e.target.dispatch({ type: 'reset' }); + form.reset(); } } -export function submitFailure(e, form) { +function submitFailure(error, form) { let errorMessage = form.querySelector('.form-message.error-message'); if (!errorMessage) { errorMessage = document.createElement('div'); @@ -32,10 +32,67 @@ export function submitFailure(e, form) { form.querySelector('button[type="submit"]').disabled = false; } -export function handleSubmit(e, form) { +function generateUnique() { + return new Date().valueOf() + Math.random(); +} + +function constructPayload(form) { + const payload = { __id__: generateUnique() }; + [...form.elements].forEach((fe) => { + if (fe.name) { + if (fe.type === 'radio') { + if (fe.checked) payload[fe.name] = fe.value; + } else if (fe.type === 'checkbox') { + if (fe.checked) payload[fe.name] = payload[fe.name] ? `${payload[fe.name]},${fe.value}` : fe.value; + } else if (fe.type !== 'file') { + payload[fe.name] = fe.value; + } + } + }); + return { payload }; +} + +async function prepareRequest(form) { + const { payload } = constructPayload(form); + const headers = { + 'Content-Type': 'application/json', + }; + const body = JSON.stringify({ data: payload }); + const url = form.dataset.submit || form.dataset.action; + return { headers, body, url }; +} + +async function submitForm(form) { + try { + const { headers, body, url } = await prepareRequest(form); + const response = await fetch(url, { + method: 'POST', + headers, + body, + }); + if (response.ok) { + submitSuccess(response, form); + } else { + const error = await response.text(); + throw new Error(error); + } + } catch (error) { + submitFailure(error, form); + } +} + +export default async function handleSubmit(e, form) { + e.preventDefault(); const valid = form.checkValidity(); if (valid) { e.submitter.setAttribute('disabled', ''); + if (form.getAttribute('data-submitting') !== 'true') { + form.setAttribute('data-submitting', 'true'); + + // hide error message in case it was shown before + form.querySelectorAll('.form-message.show').forEach((el) => el.classList.remove('show')); + await submitForm(form); + } } else { const fields = form.querySelectorAll(':invalid:not(fieldset)'); fields.forEach((field) => { diff --git a/blocks/form/util.js b/blocks/form/util.js index 956e8ad6..b872c7f5 100644 --- a/blocks/form/util.js +++ b/blocks/form/util.js @@ -195,7 +195,3 @@ export function checkValidation(fieldElement) { updateOrCreateInvalidMsg(fieldElement, ''); } } - -export function isDocumentBasedForm(formDef) { - return formDef?.[':type'] === 'sheet' && formDef?.data; -}