A New Way of Programming AJAX Style

As a programmer / web developer, I’ve been exposed to AJAX since before it was popular in jQuery. I remember creating my own $.ajax(); functions using XMLHTTP Requests, and other complicated javascript code and functions.

When exposed to jQuery, why reinvent the wheel? However, implementing the code to my current applications and websites was not that easy though. I wanted to create a sort of a system to integrate into a web app. Something that works for me. After many iterations, I came up with the following:

Where it all began

We need to trap the clicks to our app actions. In doing so, let’s look at the action buttons.

1
2
3
<body>
    <a href="#" class="btn" id="buttonone">Click Here</a>
</body>

And now, for the JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$(document).ready(function(){
    $(document)on('click','.btn',function(e){
        // This makes sure we don't follow through on the click.
        // In essence, we cancel the initial click.
        e.preventDefault();
        // Now we make an ajax call.
        $.ajax({
            url: '/ajax/buttonactions.php?action=actionone',
            success: function(data) {
                // and we output our results
                console.log(data);
            }
        });
    });
});

And our complementing PHP action file.

1
2
3
4
5
6
7
8
9
10
11
12
// To make sure we set our action
$action = isset($_GET['action']) ? $_GET['action'] : '';

// call the function passed in from the ajax call
call_user_func($action);

// the function of the same name as the parameter
// as passed in from AJAX call.
function actionone() {
    // data to return
    return "data is back";
}

We don’t know what we’re going to do with our data yet, so let’s make it make some sense. We would like to return a JSON object from our PHP, because inside the JSON object, we can pass structured HTML, as well as other JSON data to be used by JS.

Our PHP has been updated with the following (Notice the JSON Encoded array returned at the end):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// To make sure we set our action
$action = isset($_GET['action']) ? $_GET['action'] : '';

// call the function passed in from the ajax call
call_user_func($action);

// the function of the same name as the parameter
// as passed in from AJAX call.
function actionone() {
    // data to return
    $retVal = array(
        "error" => false,
        "message" => "Data is back!"
    );
    return json_encode($retVal);
}

And now, to deal with the data on JS side. Make our AJAX call be of dataType JSON. We check to see if the data returned has the error variable equal to true or false. If false, continue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$(document).ready(function(){
    $(document)on('click','.btn',function(e){
        // This makes sure we don't follow through on the click.
        // In essence, we cancel the initial click.
        e.preventDefault();
        // Now we make an ajax call.
        $.ajax({
            url: '/ajax/buttonactions.php?action=actionone',
            dataType: 'JSON',
            success: function(data) {
                // and we output our results
                if (!data.error) {
                    console.log(data.message);
                } else {
                    console.log('data return error');
                }
            }
        });
    });
});

But this is not too much fun. All of the processing and rendering would have to happen on the JS side if all we return is JSON data. Let’s put things in arrays, and nest them for future use. Also, use our Output Buffer to do the work for rendering things.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
...
function actionone() {
   
    $htmlToBeReturned = '';
    ob_start();
    ?><div>This is a block of HTML!</div><?php
    $htmlToBeReturned = ob_get_contents();
    ob_end_clean();
   
    // data to return
    $retVal = array(
        "error" => false,
        "message" => "Data is back!",
        "htmls" => array(
            "#buttonone" => $htmlToBeReturned
        )
    );
    return json_encode($retVal);
}
...
?>

Notice how we are returning HTML content inside our JSON object. It works really well too. json_encode takes care of everything for us. Also notice how we put our HTML return code inside another array called “htmls”. This is a great way to handle multiple HTML blocks that require changing. The great part about this is that you’re returning all of your data with one HTTP Request, one database call, and you’re manipulating multiple DOM blocks / elements. Another notice is the htmls object will contain the “selector” to be changed in the front end. You can have a string of these selectors, specific selectors, or a group of selectors, just like jQuery.

Our new JS code will look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
            success: function(data) {
                // and we output our results
                if (!data.error) {
                    console.log(data.message);
                    for ($html in data.htmls) {
                        $($html).html(data.htmls[$html]);
                    }
                    $('body').append();
                } else {
                    console.log('data return error');
                }
            }
...

And now we see how easy it was to manipulate the DOM via ajax. You can improve on this model by templetizing the rendering to be able to re-use the same tempalte, you can add data objects to the click element and pass them in as post parameters, etc.

This is how we templetize the rendering of the HTML:

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
<?php
...
function actionone() {
   
    $htmlToBeReturned = '';
    ob_start();
    renderHtmlBlockOne();
    $htmlToBeReturned = ob_get_contents();
    ob_end_clean();
   
    // data to return
    $retVal = array(
        "error" => false,
        "message" => "Data is back!",
        "htmls" => array(
            "#buttonone" => $htmlToBeReturned
        )
    );
    return json_encode($retVal);
}
...
function renderHtmlBlockOne() {
    ?><div>This is a block of HTML!</div><?php
}
...
?>

You can move the render functions inside a file to be included from anywhere so you can avoid duplicate render code.

Let’s make the click dynamic.

1
2
3
<body>
    <a href="#" data-action="actionone" class="btn" id="buttonone">Click Here</a>
</body>

And adjust the AJAX call to fit in any action:

1
2
3
4
...
        var $this = $(this);
        var $action = $this.attr('data-action');
...

We cached the clicked object so we don’t have to constantly refer to it via jQuery.

And the url:

1
2
3
4
5
...
        $.ajax({
            url: '/ajax/buttonactions.php?action='+$action,
            dataType: 'JSON',
...

Now, your only worries are to make sure that you assign the data-action to the clicked element to call the proper action in PHP. HTML -> JS -> PHP -> back to JS -> back to HTML. Pretty clever, huh? Input -> controller -> model -> controller -> output.

And now, for the promised bells and whistles of passing data through data attributes. We already passed in one data attribute, the action, now, we just have to add more data, and change the type of the AJAX call to post.

1
2
3
<body>
    <a href="#" data-action="actionone" data-data="id=1&type=active" class="btn" id="buttonone">Click Here</a>
</body>

In the code above, we pass in a string of data that can be dynamically generated when generating the page with PHP. In essence:

1
2
3
<body>
    <a href="#" data-action="actionone" data-data="id=<?php echo $id; ?>&type=<?php echo $type; ?>" class="btn" id="buttonone"><?php echo $actionTitle; ?></a>
</body>
1
2
3
4
5
...
        var $data = $this.attr('data-data');
...
            type: 'POST'
...

And in our PHP code,

1
2
3
4
5
6
<?php
...
    $id = $_POST['id'];
    $type = $_POST['type'];
...
?>

And that’s it. You can always improve on the code, but this is the general idea to keep things simple and expandable.

The HTML File:

1
2
3
<body>
    <a href="#" data-action="actionone" class="btn" id="buttonone">Click Here</a>
</body>

The JS file, assuming you’ve loaded jQuery:

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
$(document).ready(function(){
    $(document)on('click','.btn',function(e){
        // This makes sure we don't follow through on the click.
        // In essence, we cancel the initial click.
        e.preventDefault();
        // Now we make an ajax call.
       
        var $this = $(this);
        var $action = $this.attr('data-action');
        var $data = $this.attr('data-data');
       
        $.ajax({
            url: '/ajax/buttonactions.php?action='+$action,
            dataType: 'JSON',
            type: 'POST'
            success: function(data) {
                // and we output our results
                if (!data.error) {
                    console.log(data.message);
                    for ($html in data.htmls) {
                        $($html).html(data.htmls[$html]);
                    }
                    $('body').append();
                } else {
                    console.log('data return error');
                }
            }
        });
    });
});

And the AJAXed PHP code:

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
<?php
// To make sure we set our action
$action = isset($_GET['action']) ? $_GET['action'] : '';

// call the function passed in from the ajax call
call_user_func($action);

// the function of the same name as the parameter
// as passed in from AJAX call.
function actionone() {

    $id = $_POST['id'];
    $type = $_POST['type'];
   
    $htmlToBeReturned = '';
    ob_start();
    renderHtmlBlockOne();
    $htmlToBeReturned = ob_get_contents();
    ob_end_clean();
   
    // data to return
    $retVal = array(
        "error" => false,
        "message" => "Data is back!",
        "htmls" => array(
            "#buttonone" => $htmlToBeReturned
        )
    );
    return json_encode($retVal);
}
...
function renderHtmlBlockOne() {
    ?><div>This is a block of HTML!</div><?php
}

?>

Happy coding!