| | |
| | | } else { |
| | | this.notify('form-submit', { |
| | | config: form, |
| | | data: this.changes.get(form.id)?.changes??{}, |
| | | data: this.changes.get(form.id)?.changes ?? {}, |
| | | }); |
| | | } |
| | | if (form.options.endpoint && !form.options.handled) { |
| | | console.log('Submitting form...'); |
| | | await this.handleServerSave(form, this.collectFormData(form.form)); |
| | | } |
| | | } |
| | | if (form.options.endpoint && !form.options.handled) { |
| | | e.preventDefault(); |
| | | console.log('Submitting form...', this.changes.get(form.id)?.changes ?? {}); |
| | | await this.handleServerSave(form, this.changes.get(form.id)?.changes ?? {}); |
| | | |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if (form.tabs) { |
| | | console.log('Updating step progress on change'); |
| | | this.updateStepProgress(form); |
| | | } |
| | | |
| | |
| | | async handleServerSave(form, changes) { |
| | | this.cancelServerSave(form.id); |
| | | |
| | | if (window.jvbQueue) { |
| | | if (form.useQueue && window.jvbQueue) { |
| | | changes.user = window.auth.getUser(); |
| | | window.jvbQueue.addToQueue({ |
| | | endpoint: form.options.endpoint, |
| | |
| | | headers: form.options.headers??{}, |
| | | }); |
| | | } else { |
| | | await window.auth.fetch(jvbBase.api+form.options.endpoint, { |
| | | body: changes, |
| | | headers: form.options.headers??{}, |
| | | }); |
| | | try { |
| | | let response = await window.auth.fetch(jvbSettings.api+form.options.endpoint, { |
| | | body: changes, |
| | | headers: form.options.headers??{}, |
| | | method: 'POST', |
| | | }); |
| | | |
| | | if (!response.ok) { |
| | | let errorDetails; |
| | | try { |
| | | // Attempt to parse the server's error payload as JSON |
| | | errorDetails = await response.json(); |
| | | } catch { |
| | | // Fallback if the error response isn't JSON (e.g., HTML error page) |
| | | errorDetails = { message: response.statusText || 'Unknown HTTP error' }; |
| | | } |
| | | this.notify('form-error', { |
| | | config: form, |
| | | data: errorDetails |
| | | }); |
| | | return; |
| | | } |
| | | let result = await response.json(); |
| | | this.notify('form-success', { |
| | | config: form, |
| | | result: result |
| | | }); |
| | | } catch (error) { |
| | | if (error.status) { |
| | | this.notify('form-error', { |
| | | config: form, |
| | | data: error |
| | | }); |
| | | // This is an HTTP error thrown manually (e.g., 404, 500) |
| | | } else if (error instanceof SyntaxError) { |
| | | this.notify('form-error', { |
| | | config: form, |
| | | data: { |
| | | status: 'error', |
| | | success: false, |
| | | message: 'Something went wrong' |
| | | } |
| | | }); |
| | | // This happens if response.json() fails on a successful 200 OK response |
| | | console.error('Data Error: Server returned invalid JSON format.'); |
| | | } else { |
| | | this.notify('form-error', { |
| | | config: form, |
| | | data: { |
| | | status: 'network_error', |
| | | message: 'Network error: could not connect to the server' |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | autoUpload: false, |
| | | imageMeta: true, |
| | | delay: 1500, |
| | | useQueue: true, |
| | | endpoint: Object.hasOwn(form.dataset, 'save') ? form.dataset.save: '', |
| | | showStatus: true, |
| | | showSummary: false, |
| | |
| | | if (!Object.hasOwn(form.dataset, 'formId')) { |
| | | form.dataset.formId = window.generateID('form_'); |
| | | } |
| | | if (Object.hasOwn(form.dataset, 'action')) { |
| | | options.headers = window.auth.getHeader(form.dataset.action); |
| | | } |
| | | const formId = form.dataset.formId; |
| | | |
| | | this.addFormListeners(form); |
| | |
| | | p: 'p', |
| | | }, |
| | | setup({ el, refs, manyRefs, data }) { |
| | | const skipFields = ['sendAll', ...data.config.options.ignore??[]]; |
| | | const skipFields = ['sendAll', ...data?.config?.options?.ignore??[]]; |
| | | |
| | | for (let [key, value] of Object.entries(data.changes)) { |
| | | if (skipFields.includes(key) || form.isEmptyValue(value)) continue; |
| | |
| | | } |
| | | |
| | | refs.result?.remove(); |
| | | data.config.element.after(el); |
| | | window.fade(data.config.element, false); |
| | | } |
| | | } |
| | | ); |
| | |
| | | |
| | | field.classList.remove('has-success'); |
| | | field.classList.add('has-error'); |
| | | field.scrollIntoView({ |
| | | behavior: "smooth", |
| | | block: "center", |
| | | inline: "nearest" |
| | | }); |
| | | field.querySelector(this.inputSelectors)?.focus(); |
| | | |
| | | if (item.ui.message) { |
| | | item.ui.message.hidden = false; |
| | |
| | | window.auth.subscribe(event => { |
| | | if (event === 'auth-loaded') { |
| | | window.jvbForm = new FormController(); |
| | | document.querySelectorAll('form[data-auto]').forEach(form => { |
| | | window.jvbForm.registerForm(form, {}); |
| | | }); |
| | | } |
| | | }); |
| | | }); |