FormData from the form, posts it and shows formcarry’s answer, and the same request carries files, a spam blocker token and validation errors.
Prerequisites
Before you start, you need:- A formcarry account. Sign up is free.
- A form in the dashboard. Its endpoint is on the form’s Setup page. The examples use
https://formcarry.com/s/AbC123xyz; put yours in its place.
The request
To send a form with jQuery, build aFormData from the form element, post it with $.ajax, and send Accept: application/json so the answer comes back as JSON:
name, because FormData reads the fields from the elements and formcarry stores each value under its name. The email field is the visitor’s address, so it becomes the reply to address of your notification and the recipient of the auto response.
Set processData: false and contentType: false rather than leaving the defaults, otherwise jQuery tries to serialise the FormData itself and the request fails before it is sent.
A stored submission answers with code: 200. jQuery routes every status outside 2xx to error, so a refused submission’s answer is in xhr.responseJSON, with the reason in message, see What every form needs.
Without a file input, $(this).serialize() posts the same fields as application/x-www-form-urlencoded, with no processData or contentType to set:
serialize() leaves file inputs out, so a form that uploads keeps the FormData request.
JSON
To send JSON instead, collect the fields into an object,JSON.stringify it, and set contentType: "application/json":
Files
AFormData built from the form carries its file inputs, so the first request uploads them as is. To take one file in one field and several in another, add the inputs to the form; the same $.ajax options send them:
contentType: false rather than setting multipart/form-data yourself, otherwise the multipart boundary is missing and the upload fails.
For File objects from elsewhere, such as a Dropzone with its own upload turned off, append each one under its own name:
autoProcessQueue: false keeps Dropzone from posting to url itself, and getAcceptedFiles() returns what the visitor dropped.
For a small file inside the JSON request, read it as a data URL and give it its own key, never an array:
Files are stored on paid plans only. Free plans store the rest of the submission without them.
Validation errors
A422 carries errors, one entry per failing field, each with a message. To show each one next to its field, and every other refusal in an alert:
422 in error rather than in success, otherwise the handler never runs.
To clear the marks before the next attempt, remove them at the top of the submit handler:
Spam blocker
To add a challenge, load the vendor’s script, put adiv with the widget class and data-sitekey inside the form, and paste the secret key into the form’s settings under Form Security:
With reCAPTCHA v2:
g-recaptcha-response to the form, so the FormData request carries the token as is, and Object.fromEntries puts it into the JSON request too. With reCAPTCHA v3 there is no widget: call grecaptcha.execute("SITE_KEY", { action: "submit" }) when the visitor submits and put what it returns into a hidden input named g-recaptcha-response.
To hold the request until the visitor has passed the challenge, check the token at the top of the submit handler:
403 for reCAPTCHA or 400 for the others. Add localhost to the challenge’s allowed domains while you test.
The submit button
To stop a second submit while the request runs, disable the button before$.ajax and enable it again in complete:
complete runs after success and error alike, so the button comes back after a refused submission too. Disable the button rather than trusting one click, otherwise the second click gets a 429: 1 submission per 15 seconds per form per IP address.
To show that the request is running, swap the button text for a spinner and put the text back in complete:
complete rather than in success, otherwise a refused submission leaves the spinner in the button.
Reset
To clear the fields after a stored submission, reset the form insuccess:
success rather than in complete, otherwise a refused submission clears what the visitor typed.
What’s next
- Field validations: the rules you can set per field.
- Spam protection: the challenges, the filter and the honeypot.
- Email notifications: the auto response the visitor gets, keyed on
email.