Search code examples
javascriptjqueryformsvalidationalpacajs

Alpacajs validation: Is it possible to allow a button to skip validation and submit the form?


I have an alpacajs form with two buttons: "Save Draft" and "Submit". The behavior I'm trying to implement for these buttons is:

  • The user can click the 'Save Draft' button and submit the form even if there are empty required fields or other validation problems; their data will be saved so they can resume work on the form later; their partial data will be stored in a backend and included in the form data array when they come back.
  • The 'Submit' button behaves normally; it remains disabled until the form validates. Their final submission data will be stored in a backend, marked as completed, and locked.

The official documentation about validation is somewhat sparse and seems to imply that it may be necessary to add a custom validator to every field on the form, but I'm hoping there's a simpler way to do this; I'm imagining a custom onClick behavior for the Save Draft button like

onClick="function(){$('#form').alpaca('get').justMarkTheWholeFormValidAndGo()}"

I've been trying to get this work with the basic "Getting started" example form:

$("#form").alpaca({
    "data": {
    },
    "schema": {
        "title": "User Feedback",
        "description": "What do you think about Alpaca?",
        "type": "object",
        "properties": {
            "name": {
                "type": "string",
                "title": "Name",
                "required": true
            },
            "feedback": {
                "type": "string",
                "title": "Feedback"
            },
            "ranking": {
                "type": "string",
                "title": "Ranking",
                "enum": ["excellent", "ok", "so so"],
                "required": true
            },
        }
    },
    "options": {
        "form": {
            "attributes": {
                "action": "/path/to/submission/handler/",
                "method": "post"
            },
            "buttons": {
                "save_draft": {
                    "type": "submit",
                    "value": "Save Draft",
                    "attributes": {
                        "name": "safe_draft"
                    }
                },
                "submit": {
                    "type": "submit",
                    "value": "Submit",
                    "attributes": {
                        "name": "submit"
                    }
                }
            }
        },
        "helper": "Tell us what you think about Alpaca!",
        "fields": {
            "name": {
                "size": 20,
                "helper": "Please enter your name."
            },
            "feedback": {
                "type": "textarea",
                "rows": 5,
                "cols": 40,
                "helper": "Please enter your feedback."
            },
            "ranking": {
                "type": "select",
                "helper": "Select your ranking.",
                "optionLabels": ["Awesome!", "It's Ok", "Hmm..."]
            },
        },
        "hideInitValidationError": true
    }
});


Solution

  • You can do this by customizing the "click" event for save_draft button like this and you should change type from submit to button:

    "save_draft": {
          "type": "button",
          "value": "Save Draft",
          "attributes": {
               "name": "safe_draft"
          },
          "click": function() {
               // put here your logic to save the form data
               // and ajax call for a backend service for example
               // only data that are set will be sent in request body or you can create your own model with nullable values...
          }
    }
    

    you can also add a hidden field (see http://www.alpacajs.org/docs/fields/hidden.html) to take true/false if your going to send a draft or not, in order to use the same webservice/http url used in the form attributes.

    Then in click event method of draft_button do this:

    "click": function() {
            // setting draft to TRUE
            var control = $("#form").alpaca("get"); // getting alpaca control
            var field = control.getControlByPath("draft"); // getting the draft field
            field.setValue(true); // set value to true
            this.ajaxSubmit(); // send the data using ajax
    }
    

    And don't forget to set back the value of draft to false later in the click event of submit button.