diff --git a/packages/vulcan-forms/lib/Form.jsx b/packages/vulcan-forms/lib/Form.jsx index 00712ded5..3da5c6032 100644 --- a/packages/vulcan-forms/lib/Form.jsx +++ b/packages/vulcan-forms/lib/Form.jsx @@ -61,6 +61,8 @@ class Form extends Component { this.addToAutofilledValues = this.addToAutofilledValues.bind(this); this.addToDeletedValues = this.addToDeletedValues.bind(this); this.addToSubmitForm = this.addToSubmitForm.bind(this); + this.addToSuccessForm = this.addToSuccessForm.bind(this); + this.addToFailureForm = this.addToFailureForm.bind(this); this.throwError = this.throwError.bind(this); this.clearForm = this.clearForm.bind(this); this.updateCurrentValues = this.updateCurrentValues.bind(this); @@ -80,6 +82,8 @@ class Form extends Component { }; this.submitFormCallbacks = []; + this.successFormCallbacks = []; + this.failureFormCallbacks = []; } // --------------------------------------------------------------------- // @@ -102,7 +106,7 @@ class Form extends Component { const fieldSchema = schema[fieldName]; fieldSchema.name = fieldName; - + // intialize properties let field = { name: fieldName, @@ -111,8 +115,8 @@ class Form extends Component { layout: this.props.layout, order: fieldSchema.order } - - // hide or show the field, a function taking form props as argument & returning a boolean can be used + + // hide or show the field, a function taking form props as argument & returning a boolean can be used field.hidden = (typeof fieldSchema.hidden === 'function') ? !!fieldSchema.hidden.call(fieldSchema, this.props) : fieldSchema.hidden; // add label or internationalized field name if necessary (field not hidden) @@ -169,7 +173,7 @@ class Form extends Component { if (fieldSchema.limit) { field.limit = fieldSchema.limit; } - + // add placeholder if (fieldSchema.placeholder) { field.placeholder = fieldSchema.placeholder; @@ -312,25 +316,25 @@ class Form extends Component { // ------------------------------- Context ----------------------------- // // --------------------------------------------------------------------- // - // add error to form state + // add error to form state // from "GraphQL Error: You have an error [error_code]" // to { content: "You have an error", type: "error" } throwError(errorMessage) { let strippedError = errorMessage; - - // strip the "GraphQL Error: message [error_code]" given by Apollo if present + + // strip the "GraphQL Error: message [error_code]" given by Apollo if present const graphqlPrefixIsPresent = strippedError.match(/GraphQL error: (.*)/); if (graphqlPrefixIsPresent) { strippedError = graphqlPrefixIsPresent[1]; } - + // strip the error code if present const errorCodeIsPresent = strippedError.match(/(.*)\[(.*)\]/); if (errorCodeIsPresent) { strippedError = errorCodeIsPresent[1]; } - + // internationalize the error if necessary const intlError = Utils.decodeIntlError(strippedError, {stripped: true}); if(typeof intlError === 'object') { @@ -343,7 +347,7 @@ class Form extends Component { content: strippedError, type: 'error' }; - + // update the state with unique errors messages this.setState(prevState => ({ errors: _.uniq([...prevState.errors, error]) @@ -372,6 +376,16 @@ class Form extends Component { this.submitFormCallbacks.push(callback); } + // add a callback to form submission success + addToSuccessForm(callback) { + this.successFormCallbacks.push(callback); + } + + // add a callback to form submission failure + addToFailureForm(callback) { + this.failureFormCallbacks.push(callback); + } + setFormState(fn) { this.setState(fn); } @@ -388,6 +402,8 @@ class Form extends Component { getDocument: this.getDocument, setFormState: this.setFormState, addToSubmitForm: this.addToSubmitForm, + addToSuccessForm: this.addToSuccessForm, + addToFailureForm: this.addToFailureForm, }; } @@ -421,6 +437,9 @@ class Form extends Component { this.clearForm({clearErrors: true, clearCurrentValues}); } + // run document through mutation success callbacks + result = runCallbacks(this.successFormCallbacks, result); + // run success callback if it exists if (this.props.successCallback) this.props.successCallback(document); @@ -433,7 +452,10 @@ class Form extends Component { console.log("// graphQL Error"); // eslint-disable-line no-console console.log(error); // eslint-disable-line no-console - + + // run mutation failure callbacks on error, we do not allow the callbacks to change the error + runCallbacks(this.failureFormCallbacks, error); + if (!_.isEmpty(error)) { // add error to state this.throwError(error.message); @@ -451,7 +473,7 @@ class Form extends Component { if (this.state.disabled) { return; } - + this.setState(prevState => ({disabled: true})); // complete the data with values from custom components which are not being catched by Formsy mixin @@ -464,7 +486,7 @@ class Form extends Component { // run data object through submitForm callbacks data = runCallbacks(this.submitFormCallbacks, data); - + const fields = this.getFieldNames(); // if there's a submit callback, run it @@ -543,7 +565,7 @@ class Form extends Component { > {this.renderErrors()} {fieldGroups.map(group => )} - +
{this.props.cancelCallback ? {this.props.cancelLabel ? this.props.cancelLabel : } : null} @@ -612,6 +634,8 @@ Form.childContextTypes = { addToAutofilledValues: PropTypes.func, addToDeletedValues: PropTypes.func, addToSubmitForm: PropTypes.func, + addToFailureForm: PropTypes.func, + addToSuccessForm: PropTypes.func, updateCurrentValues: PropTypes.func, setFormState: PropTypes.func, throwError: PropTypes.func,