Form submission
Default form submission
When a user clicks the submit button, the submit action is fired the ChangesetWebform component.
The following series of events occurs.
Preflighting
A preflight function is run which:
- Validates all fields.
- Calls the
afterValidateFieldsaction.- If validation fails it calls the
formValidationFailedaction. - If validation passes it:
- Calls the
formValidationPassedaction. - Calls the
beforeSubmitFormaction. - For any fields that are omitted, the corresponding changeset proprties are set to null. See Hiding and showing fields for more.
- Calls the
- If validation fails it calls the
Activation of the tracked requestInFlight property
The tracked property changesetWebform.formSettings.requestInFlight is set to true. This can be used to create a UX which shows the user that a response is pending.
The changeset is saved
The changeset is saved using the changeset.save() method. This means that if your changeset is an Ember model, the models save method will be triggered, which will update the record in Ember Data, but also send a PATCH request to the server to persist those changes.
Call the submitData action if passed
If @submitData is passed to theChangesetWebformcomponent it will be called at this point.
Unless your changeset is an Ember model, you will need to use this action to trigger a network request, if that is required.
An example would be to make a POST request to the sever, to persist a new record to the database.
Deactivation of the tracked requestInFlight property
The tracked property changesetWebform.formSettings.requestInFlight is set to false. This can be used to create a UX which shows the user that a response is complete.
The submitSuccess or submitError actions are called if passed
If @submitSuccess is passed to the ChangesetWebform component it will be called if the changeset.save() and submitData actions are successful. The response is included as the first argument. If @submitError is passed to the ChangesetWebform component it will be called if either the changeset.save() or submitData actions are unsuccessful. The error response is included as the first argument.
import React from 'react'; import ChangesetWebform from 'react-changeset-webforms/src/components/ChangesetWebform.jsx'; const formSchema = { formSettings: { formName: 'defaultFormSubmission', }, fields: [ { fieldId: 'name', fieldType: 'input', fieldLabel: 'Name', validationRules: [ { validationMethod: 'validatePresence', arguments: true, }, ], }, ], }; const serverResponseFormSchema = { formSettings: { formName: 'defaultFormSubmission', hideSubmitButton: true, }, fields: [ { fieldId: 'serverResponseType', fieldType: 'radioButtonGroup', fieldLabel: 'Server response type', options: ['Asynchronous success response', 'Asynchronous error response', 'Synchronous success response', 'Synchronous error response'], }, ], }; export default function DefaultFormSubmission() { const [serverResponseType, setServerResponseType] = React.useState('Asynchronous success response'); const serverResponseTypeRef = React.useRef(serverResponseType); const [alert, setAlert] = React.useState(null); function submitData(data, _changesetWebform) { const responseType = serverResponseTypeRef.current; if (responseType.startsWith('Asynchronous')) { return new Promise((resolve, reject) => { setTimeout(() => { if (responseType.includes('error')) { reject(new Error(responseType)); } else { resolve(responseType); } }, 500); }); } else { if (responseType.includes('error')) { throw new Error(responseType); } else { return responseType; } } } function submitSuccess(response) { setAlert({ type: 'success', message: response }); } function submitError(error) { setAlert({ type: 'danger', message: error.message }); } function onFieldValueChange(formField) { console.log('Field value changed', formField.fieldValue); serverResponseTypeRef.current = formField.fieldValue; setServerResponseType(formField.fieldValue); } function removeAlert() { setAlert(null); } return ( <> <div className="bg-light px-4 py-1 border-bottom"> <ChangesetWebform formSchema={serverResponseFormSchema} onFieldValueChange={onFieldValueChange} data={{ serverResponseType }} /> </div> {alert && ( <div data-test-id="default-form-submission-alert" className={`alert alert-${alert.type}`} > {alert.message} <button type="button" data-test-id="remove-alert" onClick={removeAlert} /> </div> )} <ChangesetWebform formSchema={formSchema} submitData={submitData} submitSuccess={submitSuccess} submitError={submitError} /> </> ); }
Custom form submission
If the @onFormSubmit action is passed to the ChangesetWebform component, it will completely override all default form submission behaviour.
The action receives the changesetWebform object as its only argument.
The example below also shows how the preflight util can be invoked if needed (See Preflighting above).
import React from 'react'; import ChangesetWebform from 'react-changeset-webforms/src/components/ChangesetWebform.jsx'; import { preFlightForm } from 'validated-changeset-webforms'; const formSchema = { formSettings: { formName: 'customFormSubmission', }, fields: [ { fieldId: 'name', fieldType: 'input', fieldLabel: 'Name', validationRules: [ { validationMethod: 'validatePresence', arguments: true, }, ], }, ], }; export default function CustomFormSubmission() { const [alert, setAlert] = React.useState(null); async function onFormSubmit(changesetWebform) { await preFlightForm(changesetWebform); if (!changesetWebform.changeset.isValid) { return; } setAlert({ type: 'success', message: 'A completely custom form submission action was run.', }); } return ( <> {alert && ( <div data-test-id="custom-form-submission-alert" className={`alert alert-${alert.type}`} > {alert.message} </div> )} <ChangesetWebform formSchema={formSchema} onFormSubmit={onFormSubmit} /> </> ); }