Wednesday 28 January 2015

Keep the state with single page application

Loading only one page when you run a single page application (SPA) is not the only benefit of this model for building an application. I think keeping the state of the application in the client's browser is the most important features we can get benefit from it.

Regardless of the way or technology you use to build your web application, if you change or reload the pages, you know you always have a problem of how to pass the state or tracking information from one page to another.

Sample model for SPA
Building SPA with no framework 
Honestly, i hate frameworks, they come and go, sometimes don't have backward compatibility, and many of them don't care about how many people get addicted to and used them. (I know this is life.)

Look at the picture, development of such an application is so easy even without any framework. If you want to do it cleanly, you need to write it in JavaScript OOP like and have the application objects talk to the back end through Ajax request/response.

Writing such an application especially when you want to change UI components or their parameters most of the time is easier than handling them in a fixed HTML tag based application with JavaScript. OK, let us see how we can develop such an application.



Sample SPA
One way to design a class is to see how we want and it is natural to use it. So I suggest using the application's main class like the following: (uploaded version is here)

<html>
<body>
<div id="mainContainer" class="mainContainer"></div>
</body>
<script type="text/javascript" src="/includes/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="/includes/components.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        var myApp = new MyApplication({
                parentContainer : $("#mainContainer")
        });
        myApp.init();
        myApp.navigate();
    });
</script>
</html>

As you see we have nothing but a single div in which we want to render our application. The benefit of this form of web applications is that you can have another instance in the same page if you want. You just need to instantiate another one, and believe me it works and opens windows of better UI/UX to you, like this:

var myApp2 = new MyApplication();
myApp2.init();
myApp2.navigate();

Now let us see how this JavaScript application class should look like. I am going  to write all the needed classes in components.js, (although it is not a must to keep them all in a single .js file) this is what the main class of the application looks like:

function MyApplication(options) {

        this.init = function() { 
        }

        this.navigate = function() {
        }

        var buttonClick= function() {
        }
}

Note that this is a convention of having the first character of the function in capital if you want to use it as a class, do not try to avoid it. This helps you to remember that MyApplication is not a function, it is a class and you should get an instance of it before using.

The methods introduced like "this.init" are public which can be called from outside of the class body and those who are defined as variable are only accessible from the inside of the class. I usually put variable definition and initialization at the  top of the complete class should be something like this:

function MyApplication(options) {
    "use strict";

    var divMainContainer = $("<div/>");
    var divMessage = $("<div/>");
    var buttonAddBox = $("<button/>");

    var messageColor = "red";
    var boxId = 0;

    if (typeof options.parentContainer === "undefined")
        options.parentContainer = $("body");

    this.init = function() {
        divMainContainer.addClass("divMainContainer");
        options.parentContainer.append(divMainContainer);

        divMessage.addClass("message");
        divMessage.attr("id", "idMessage");
        divMessage.append("this is a dynamic web content, click the button bellow ...");
        divMainContainer.append(divMessage);

        buttonAddBox.append("add box");
        buttonAddBox.css({
            "margin-bottom" : "10px",
            "margin-left" : "10px"
        });
        divMainContainer.append(buttonAddBox);
    }

    this.navigate = function() {
        buttonAddBox.click(buttonClick);
    }

    var buttonClick = function() {
        if (messageColor === "red") {
            messageColor = "blue";
        } else {
            messageColor = "red";
        }

        $(this).css({
            color : messageColor
        });

        boxId = boxId + 1;
        var myBox = new MyRandomBox(options.parentContainer, boxId);
        // you may need the reference "myBox" later ....
    }
}

As you see I have defined and created all the components I need in the UI in the class itself. And in the init method I just set classes and styles of the components and append them to their related parents. And in the navigate method I usually do the things that make application to response to user requests. Not that in this example I didn't make any Ajax request, just consider you can send Ajax requests anytime you want and get the results and use them to set up your components.

What the single button created in the application does, is that whenever you click it, it creates an instance of a class nothing else. But this class creates a box and put it on the screen. This is the piece of code which does it:

var myBox = new MyRandomBox(options.parentContainer, boxId);

What ever MyRandomBox is, the application just creates an instance of it and if it requires it may call the some other methods of the new instance too. So MyRandomBox can be as simple as this:

function MyRandomBox(container, boxId) {
    "use strict";

    var divRandomBox = $("<div/>");
    divRandomBox.addClass("randomBox");
    divRandomBox.append(boxId);
    container.append(divRandomBox);
}

I hosted a sample here in google drive, take a look at it, how it works and the source code too. Note that this was just a simple application, consider it as a business application with many business classes, this is the only way you can handle such an application.

No comments:

Post a Comment