Freeform Freeform for ExpressionEngine

Submitting a form using AJAX

To submit a form using AJAX - pass the serialized form data as the payload when posting to any front-end URL.

WARNING

This solution currently will not work with multi-page forms.

Return values

The AJAX request must be a post request and it will return a JSON object with the following values:

On successful single-page form post

  • success - A boolean value of true
  • finished - A boolean value of true
  • returnUrl - The return URL specified for the form
  • submissionId - An int value of the submission ID if one was generated

On form error

  • success - A boolean value of false
  • finished - A boolean value of false
  • errors - An object of field handles as keys and each containing an array of error messages.
    • An example, if the form's firstName and lastName fields were required, but not filled out, the returning object would be:
"errors": {
  "firstName": ["This field is required"],
  "lastName": ["This field is required"]
}
1
2
3
4

Usage in Templates

Here's a fully working Bootstrap form AJAX example:

<script>
  $(function () {
    $("form").on({
      submit: function () {
        var $self = $(this);
        $(".alert.alert-success").remove();
        $("button[type=submit]", $self).prop("disabled", true);

        $.ajax({
          type: "post",
          dataType: "json",
          data: $(this).serialize(),
          success: function (response) {
            $("ul.errors.help-block", $self).remove();
            $(".has-error", $self).removeClass("has-error");

            if (response.success && response.finished) {
              $self[0].reset();

              var $successMessage = $("<div>", { "class": "alert alert-success" })
                .append("<p>Form submitted successfully</p>", { "class": "lead" });

              $self.before($successMessage);

            } else if (response.errors) {
              for (var key in response.errors) {
                if (!response.errors.hasOwnProperty(key)) continue;
                var messages = response.errors[key];
                var $errors = $("<ul>", { "class": "errors help-block" });
                for (var i = 0; i < messages.length; i++) {
                  var $li = $("<li>");
                  $li.html(messages[i]);
                  $errors.append($li);
                }

                var $input = $("*[name=" + key + "], *[name='" + key + "[]']");

                const $formGroup = $input.parents(".form-group");
                $formGroup.addClass("has-error");

                $formGroup.append($errors);
              }
            }

            if (response.honeypot) {
              var honeypotInput = $("input[name^=freeform_form_handle_]", $self);
              honeypotInput.attr("name", response.honeypot.name);
              honeypotInput.attr("id", response.honeypot.name);
              honeypotInput.val(response.honeypot.hash);
            }

            $("button[type=submit]", $self).prop("disabled", false);
          },
        });

        return false;
      },
    });
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

If you wish to send POST data without using jQuery, be sure to set the request header manually:

const request = new XMLHttpRequest();

request.open('POST', url);
request.setRequestHeader('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest');
request.setRequestHeader('Content-type', 'application/json');
request.send(params);
1
2
3
4
5
6