AJAX – Send or receive data (without reloading the page)

JavaScript

0 Comments

JavaScript gives us a way to contact the web server (without reloading the page). This style of programming a page is typically called AJAX. AJAX technically stands for Asynchronous Javascript and XML, but don't worry about the name. Just think of it as a way to send or receive data from the server (without reloading the page). This is very useful and can make your page more like an app than a traditional web page.

Using GET to send and receive a message

Take a look at the example below. When you click the "Send PING" button, the script uses AJAX to contact a ping-pong.php script on the server. The server then responds with "PONG", and its response is added to the page.

HTML

<input type="button" id="myButton" value="Send PING">

<p id="responseContainer"></p>

We'll now build this page piece by piece.

Make the button call our sendPing function

function setupButton() {
    var myButton = document.querySelector('#myButton');

    // Run our sendPing function when someone clicks the button
    myButton.addEventListener('click', sendPing);
}

setupButton();

This code should look very familiar. In the next section we'll create the sendPing function.

Sending the AJAX request to the server

function sendPing() {
    // URL to contact using AJAX
    var url = '/examples/javascript-tutorial/ajax/ping-pong.php';

    // name=value pairs we'll be sending to the server.
    var data = 'action=ping&testName=testValue';

    // GET requires we add the name=value pairs to the end of the URL.
    url += '?' + data;

    // Create a new AJAX request object
    var request = new XMLHttpRequest();

    // Open a connection to the server
    request.open('GET', url);

    // Run our handleResponse function when the server responds
    request.addEventListener('readystatechange', handleResponse);

    // Actually send the request
    request.send();
}

The AJAX URL must be on the same domain as your JavaScript

If you try to use a URL for another domain, the browser won't allow it by default (for security reasons). There is a way around this, but I don't want to cover it at this point.

How the += operator works

url += '?' + data;

The above code is a short way to write:

url = url + '?' + data;

When you use the + operator with strings, it connects the two strings together and returns the new result. This is called concatenation.

Handling the server's response

/*
This function gets called every time something changes
with our AJAX request.
*/
function handleResponse() {
    // "this" refers to the object we called addEventListener on
    var request = this;

    /*
    Exit this function unless the AJAX request is complete,
    and the server has responded.
    */
    if (request.readyState != 4)
        return;

    // If there wasn't an error, run our showResponse function
    if (request.status == 200) {
        var ajaxResponse = request.responseText;

        showResponse(ajaxResponse);
    }
}

The this keyword

In our sendPing function, we setup the event handler with the following code:

// Run our handleResponse function when the server responds
request.addEventListener('readystatechange', handleResponse);

When the 'readystatechange' event fires and our handleResponse function is run, it has access to a hidden variable called this.

With event handlers, this always refers to what is in front of ".addEventListener". In this case, this refers to the AJAX request object (that we stored in the request variable).

request.readyState

if (request.readyState != 4)
    return;

Our handleResponse function actually gets called 4 times during an AJAX request. Our code only cares about the 4th time it's called, which is when the request is complete, and the server has responded. That's why we used the previous code.

request.status

This gives us the HTTP status code returned by the server.

  • 200 means everything was OK
  • 404 means the page was not found
  • 500 means internal server error
  • And so on

Showing the server's response on the page

function showResponse(ajaxResponse) {
    var responseContainer = document.querySelector('#responseContainer');

    // Create a new span tag to hold the response
    var span = document.createElement('span');
    span.innerHTML = ajaxResponse;

    // Add the new span to the end of responseContainer
    responseContainer.appendChild(span);
}

As you can see from above, you can actually create new HTML elements using JavaScript. You can manipulate the element just like any DOM element (even before adding it to the page). For example, you can add new attributes with setAttribute.

Using POST instead of GET

We only need to change the sendPing function to use POST instead of GET. The changed lines are highlighted.

function sendPing() {
    // URL to contact using AJAX
    var url = '/examples/javascript-tutorial/ajax/ping-pong.php';

    // name=value pairs we'll be sending to the server.
    var data = 'action=ping&testName=testValue';

    // Create a new AJAX request object
    var request = new XMLHttpRequest();

    // Open a connection to the server
    request.open('POST', url);

    // Run our handleResponse function when the server responds
    request.addEventListener('readystatechange', handleResponse);

    /*
    Add a new "Content-type" HTTP header.
    This tells the server we're sending name=value pairs
    (just like a normal form POST request would).
    */
    request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

    // Actually send the request (with the POST data)
    request.send( data );
}

Practice Problem - Use AJAX to make our mini quiz more secure

In our previous mini quiz project, we stored the correct answer in the data-answer attribute of the submit button. This works fine for a simple quiz that isn't graded, but what if this quiz were used at a college? You'd want something more secure to stop cheating.

Use what you just learned about AJAX to make our mini quiz more secure. Instead of using the data-answer attribute, you'll want to submit the answer to the server. The server will then check the answer and respond with whether or not it was correct.

Requirements

  • You can use GET or POST
  • Server URL to send the answer: /examples/javascript-tutorial/ajax/mini-quiz.php
  • Server expects "answer=userAnswer" as a name=value pair
  • The server will respond with "Correct" or "Incorrect" (this will be wrapped in a span tag). You can put the server's response directly in the p tag with class="result".
  • You must run your code from our Online HTML Editor because it won't work if the request comes from another domain.

Example

HTML

<style>
    .correct,
    .incorrect {
        font-weight: bold;
    }

    .correct {
        color: green;
    }

    .incorrect  {
        color: red;
    }
</style>

<form id="quizQuestion">
    <p>
        What JavaScript event is fired when the page is fully loaded?
    </p>

    <input type="text" name="answer">

    <input type="submit" value="Submit">

    <p class="result"></p>
</form>

JavaScript

Open Editor

// Make quizForm a global variable, so it can be accessed anywhere
var quizForm;

function setupQuiz() {
    quizForm = document.querySelector('#quizQuestion');

    quizForm.addEventListener('submit', checkAnswer);
}

function checkAnswer(event) {
    // Don't submit the form to the server
    event.preventDefault();

    var answerBox = quizForm.querySelector('input[name="answer"]');
    var userAnswer = answerBox.value;

    sendAnswer(userAnswer);
}

function sendAnswer(answer) {
    // URL to contact using AJAX
    var url = '/examples/javascript-tutorial/ajax/mini-quiz.php';

    // name=value pairs we'll be sending to the server.
    var data = 'answer=' + encodeURIComponent(answer);

    // Create a new AJAX request object
    var request = new XMLHttpRequest();

    // Open a connection to the server
    request.open('POST', url);

    // Run our handleResponse function when the server responds
    request.addEventListener('readystatechange', handleResponse);

    /*
    Add a new "Content-type" HTTP header.
    This tells the server we're sending name=value pairs
    (just like a normal form POST request would).
    */
    request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

    // Actually send the request (with the POST data)
    request.send( data );
}

/*
This function gets called every time something changes
with our AJAX request.
*/
function handleResponse() {
    // "this" refers to the object we called addEventListener on
    var request = this;

    /*
    Exit this function unless the AJAX request is complete,
    and the server has responded.
    */
    if (request.readyState != 4)
        return;

    // If there wasn't an error, run our showResponse function
    if (request.status == 200) {
        var ajaxResponse = request.responseText;

        showResponse(ajaxResponse);
    }
}

function showResponse(ajaxResponse) {
    var result = quizForm.querySelector('.result');

    result.innerHTML = ajaxResponse;

    // Make the result visible
    result.style.display = "block";
}

setupQuiz();

Leave a Comment