Friday 2 August 2013

Sending POST Requests with jQuery


An HTTP POST request is simply an HTTP request that can have any type of data attached to it. You're probably familiar with their use when submitting web forms. When writing jQuery-powered sites, being able to submit such requests dynamically becomes an essential technique.

Getting Started

jQuery POST requests are sent using the $.ajax() method. It is the underpinning of all asynchronous requests sent with jQuery, but in this article we're going to focus on sending POST requests with it.
This is the basic syntax of a POST request:

$.ajax({
            type: 'POST',
            url: 'destination.php',
            data: [your data],
            success: function(data, textStatus, jqXHR) {
                // Handle a success state
            },
    error: function(jqXHR, textStatus, errorThrown) {
                // Handle an error state
            }
});

We're only passing one parameter to the function—a set of key/value pairs. Let's look at them in more detail:
  • typeThis is where we tell $.ajax() that we want to use a POST request, instead of another type (such as GET). We're only going to cover POST, but keep in mind that there are other request types to suit other needs.
  • urlThis is where we specify the URL to submit the request to. This is usually a script on the server which processes the data and sends a response. We're pointing to a relative file path, in this example, but you can also specify a full URL.
  • dataThis is where we specify the data we want to submit with the POST request. The data can literally be anything, but often-times it is key/value pairs from a form. We could construct the data ourselves, or use jQuery's handy serialize() method that does it automatically.
  • successIf the server responds with a success message, this function will be executed. In this case, we've defined an anonymous function, but you can also define a callback here. The function takes as parameters the data returned by the server, a textual status message, and a copy of the jqXHR object (a type of XMLHttpRequest).
  • errorIf the server responds with an error, this function is executed instead. The function gets passed a copy of the jqXHR object, a text message indicating the status, and if an HTTP error is thrown, the third parameter indicates the error message.
There are a large number of other attributes that can be defined, such as dataType, username, password, etc. The full range of keys that can be sent is defined in the API page for the $.ajax() method.

A Common Scenario

The best way to explain the use the method for sending POST requests is by walking through an example. Think of any given web form—we'll use a fairly standard contact form here:

jQuery POST requests can serve two important functions to enhance this form:
  • Submit the form without a page refresh
  • Validate fields before the form is submitted
There are many other types of forms that allow for even more innovative uses of POST requests, such as checking username availability on a signup form, providing suggestions as the user fills out a search field, auto-saving every change in an Options page, etc. But let's first focus on these two common tasks and how they can be accomplished with jQuery.

Submit the form without a page refresh

A common requirement of modern web forms is that the page doesn't refresh when the form is submitted, but instead some other action happens (such as the form being replaced with a Thank You message).
Thanks to JavaScript, the standard browser behavior for submitting web forms can be short-circuited. Through attaching an event handler to the form, jQuery can handle the submission and prevent the browser from sending the standard request and redirecting the page. After jQuery is loaded, attaching a handler to a form is done using this JavaScript:

$(document).ready(function() {
        $('#formId').submit(function() {
            // Handle the submission
            return false;
        });
});

As you can see, jQuery makes this behavior extremely simple. '#formId' is the jQuery selector to target the <form>element on the page—in this case a reference to the element's id.
The event is handled through the use of an anonymous function. If the function returns false, the browser will not continue to submit the form. If it returns true, the browser will continue submitting the form as usual.
Before the return statement, you have an opportunity to post the form data with jQuery and display a response to the user (or do anything else you need to do). The code doesn't have to get much more complex:

$(document).ready(function() {
        $('#formId').submit(function() { 
                $.ajax({
                        type: 'POST',
                        url: 'process_form.php', 
                        data: $('#formId').serialize(), 
                        success: function(data, textStatus, jqXHR) {
                                $('#formId').replaceWith(''<div class="success">Thank you for contacting us!'</div>');
                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                                $('#formId').replaceWith(''<div class="error">Error!'</div>');
                        }
                });
    
                return false;
        });
});

Now when the form is submitted, instead of sending the user to a whole new page, we only load one element into the existing page to replace the form:
That concludes our efforts to submit the form using a jQuery POST request. Next up is validation.

Validate the fields before the form is submitted

Traditionally, form validation occurs after the form is submitted. If any fields fail validation, the user is redirected back to the form with some additional markup indicating what was invalid.
With JavaScript, we can validate the fields in the form's submit() function (the same one we used to submit the form above). But normal JavaScript validation means the JS code defines the validation rules. This causes an issue if JavaScript is disabled, because the form won't be validated. Thus JavaScript validation can't be relied upon alone, so we need server validation to fall back on if needed.
Thanks to jQuery POST requests, we can avoid duplicating effort and simply validate the fields using an AJAX request to the server. This can be done inside a keyup callback, like this:

$(document).ready(function() {
        $('#email_field').keyup(function() {
                if ('#email_field').val().length >= 5) {
                        // Validate the input of #email_field
                }
        });
});

If the length of the email field value is five characters or greater, then when the next keyboard key is released the field will be validated. Each request's response overwrites the previous, so when the user is done typing, the full email address will be validated properly.
Or your validation can occur right before the form is submitted, such as this:

$(document).ready(function() {
        $('#form_id').submit(function() {
                // Validate all of the inputs
        
                return true; // Or submit the form with AJAX and return false
        });
});

In this case, you could also return false if validation fails for a required field, which would prevent the form from being submitted. If you do that, it would also be wise to display a message to the user about why the form was not sent yet.
Let's validate our email field. We'll add an empty <div id="validate-email"></div> tag after our email input, and it can be positioned however we'd like with CSS. Our $.ajax() function for validating the field would go in either of the two blocks above, and it might look like this:

$.ajax({
                type: 'POST',
                url: 'validate.php',
                data: $('#email_field').serialize(),
                success: function(response) {
                        $('#validate-email').html(response.msg);
                }
});

To break down what we're doing, the above request can be read like this: We're sending a POST request to validate.php containing the serialized value of our #email_field element. Next, we're outputting the response of that validation in the existing #validate-email div on the page. Of course, you can send the request to any URL that contains your validation script.
You can also serialize multiple values (or the form itself) and send that, depending on how your validation script on the server expects to receive the data.
In the case that an email address wasn't entered, this might be the resulting validation message and field:


Rinse and repeat for each field requiring live validation, and you're all set!

Other uses for POST requests

As mentioned, there are many other ways that you can use POST requests to enhance forms, as well as perform other actions. To get you started, lets expand on some of the possible ideas:

Live username availability checking

On your subscription form, jQuery can send a POST request to the server to check if the username is available, and inform the user before they try submitting the form if they need to pick a different one.



It could even provide suggestions for other names which are available. Like many other POST requests, you could also use a GET request in much the same way depending on your preference and server scripting.

Providing search suggestions

As each key of your search form is released, jQuery could request a set of search suggestions from the server using a POST request containing the text the user entered so far.

It's a great way to help users figure out how to find what they're looking for on your site.

Auto-saving input fields

Many applications on and off the web choose to save the options you select in a form, such as profile settings, as you enter them, rather than submitting the entire form after you're finished editing everything. This can come in handy because users don't have to scroll to the end of the form and submit it just to change a couple of options at the top.

POST vs GET: How to Choose

As with most things, the answer to this is "it depends." While it's true that sometimes it makes no difference at all, other times it is very important which type of request is used. As a guiding principle, it's common practice to use a GET request when requesting data from the server, and a POST request when sending data to the server or when the intent of the request is to make a change to the server in some way.
Here are some scenarios when you should usually send a POST request:
  • If the server expects a POST request
  • If the data you're sending might be too long to fit in a URL
  • If you're submitting data that is intended to make some change occur on the server
There are also good reasons to use a GET request instead:
  • If the server expects a GET request
  • If you're not sending data, but only making a request
  • If the data is short and easily encoded into a URL, such as a search query
Many times it may not truly matter which method is used. In that case, it's usually best to simply follow the conventions of the other requests in your application.

Tips for Developers

It's easy to jump in and start filling your pages with AJAX requests, but first, there are a few tips that are good to keep in mind.

Using the shortcut method

$.ajax() might be the underpinning of all AJAX-related functionality in jQuery, but it's rarely the easiest method to use to send a request. The $.post() function is a handy alternative if you only need a success callback.
This:

$.ajax({
                type: 'POST',
                url: 'submit.php',
                data: $('#form').serialize(),
                success: function() {
                        // Do something
                }
});
 
Becomes this:

$.post('submit.php', $('#form').serialize(), function() {
        // Do something
});
 
As you can see, the shorthand function is a lot simpler, although it does not allow for all of the advanced options that $.ajax() does (such as an error callback). That leads us to our next tip...

Specifying global AJAX options

If you find yourself specifying the same options over and over again in your $.ajax() calls, or if you find you can't use the options you really need in a $.post() request but you don't want to switch to a full $.ajax() call throughout your code, you can specify the default settings for all AJAX calls with the $.ajaxSetup() function.
Here is an example specifying several default options:

$.ajaxSetup({
                url: 'validate.php',
                type: 'POST',
                dataType: 'json',
                error: function() {
                        // Do something when any AJAX error occurs
                }
});
 
Now we can write our validation functions as easily as:

$.ajax({
                data: $('#field_id').serialize(),
                success: function() {
                        // Do something
                }
});
 
Since $.ajaxSetup() options also work for $.post() calls, it's useful for specifying the options you can't specify in$.post(), such as an error function, authentication details, etc.

Avoid synchronous requests, or too many asynchronous requests

AJAX is meant to enhance the browsing experience, not frustrate the user. The more requests you're sending to your server at once, the more likely it is that one or more of them will be slow, detracting from your UI usability. As a rule, send requests only when you have to, and combine multiple queries into a single request whenever possible.
Likewise, setting the async property in $.ajax() to false will often cause the browser window to appear to freeze while the request is processing, in many causes causing a bad experience for the user. It also means any other AJAX requests will have to wait until the one running finishes. Unless you have a good reason for using synchronous requests, it's best to just leave the async property set to true.

The Power of AJAX in Your Hands

In this article we've discussed how to send POST request with jQuery, and gone through some basic examples of its usage. We also covered a few tips on best usages and practices to avoid.
When used properly, AJAX can bring your web application to the next level. While not as common as GET requests, being able to send POST requests with jQuery is an indispensable tool when developing dynamic sites on the web today, and one you'll soon wonder how you ever got by without.