Tuesday, October 29, 2013

Templating with KnockoutJS

Another nice feature of KnockoutJS is the ability to have templates to display your data. For instance, say that if you have a collection of data and you want them to be displayed in a particular format without having to do much DOM manipulation. This can be achieved in two ways when it comes to KnockoutJS;


  • Using jQuery based templating
  • Using native knockout templating
In this tutorial i will show you both the ways and you will see why you would always want to use the native KnockoutJS templating given its unobtrusive nature.

So first off let us look at the example below;


 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
 <title>Superhero Registration</title>
</head>

<body>

 <div data-bind="template:'superHeroTemplate'">
  
  
 </div>


<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="jquery-tmpl.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>

 <script type="text/javascript">
 
 $(function(){
   
   var data = [
    new superHero('Superman'),
    new superHero('Spiderman')
   ];
   
   var viewModel = {
    superHeroes:ko.observableArray(data)
   };
   
   function superHero(name){
    return {
     name:ko.observable(name)
    };
   }
   
   ko.applyBindings(viewModel);
  }
  );
 </script>
<script id="superHeroTemplate" type="text/html">
 <ul>
  {{each superHeroes}} 
   <li>${name}</li>
  {{/each}}
  
 </ul>
</script>
</body>
</html>

Ok i am obsessed with superheroes hence the use of examples follow the same pattern. Here what i am doing is constructing an observable array of super heroes.


 
function superHero(name){
    return {
     name:ko.observable(name)
    };
   }

The above function wraps the passed in input parameter to an observable object and passes it back. This is not required, but i have done as such so that Knockout will manage not only the observable array, but also the elements within the array since these are now observable objects themselves.

Here i am using jQuery templating and as such you need one additional script file to be included which you can dowload from here. Then you need to include it on your path in order for this example to work. I have saved this script file as jquery-tmpl.js. Note that the order you include these scripts are important as well. First it should be the jQuery script, then the jQuery template script and finally the KnockoutJS script.

First in the root element we need to define the template we are going to use. This is done as follows;


 
<div data-bind="template:'superHeroTemplate'">

Here you can see in the data-bind attribute i have defined the template as superHeroTemplate. Now this name is the name i have used as the id attribute within the template script i have used below;


 
<script id="superHeroTemplate" type="text/html">
 <ul>
  {{each superHeroes}} 
   <li>${name}</li>
  {{/each}}
  
 </ul>
</script>

Note that i have specified the type as text/html here since i do not want the browser to interpret this script tag since we are using this for the sole purpose of templating. The superHeroes attribute i have defined within the each tag is the name in my viewModel which is shown below. Also the ${name} attribute is what i am returning from the superHero function that returns obserable objects when passed in the name of the super hero.


 
 var viewModel = {
    superHeroes:ko.observableArray(data)
   };

This is all that is required for this to work. One thing you might have noticed is that this is a bit too obtrusive in terms of using additional DOM and script tags to make this work. This looks more of a hack since we are specifying script tags with a type calls text/html which is not valid just to make the templating work. This is where the native Knockout templating comes in handy. Let us look at how you can do the same using that and you will see why that is much cleaner.



 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
 <title>Superhero Registration</title>
</head>

<body>

 <div>
  <ul>
   <!-- ko foreach:superHeroes -->
    <li data-bind="text: $data.name"></li>
   <!--/ko-->
  </ul>
  
 </div>


<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="jquery-tmpl.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>

 <script type="text/javascript">
 
 $(function(){
   
   var data = [
    new superHero('Superman'),
    new superHero('Spiderman')
   ];
   
   var viewModel = {
    superHeroes:ko.observableArray(data)
   };
   
   function superHero(name){
    return {
     name:ko.observable(name)
    };
   }
   
   ko.applyBindings(viewModel);
  }
  );
 </script>

</body>
</html>

As you can see, no script tags were used. You directly work on the DOM and only need to add HTML comments block and write your code within that. You can even get rid of writing it within comments and directly embed the foreach loop within the DOM element as follows;


 
<div>
  <ul data-bind="foreach:superHeroes">
   <li data-bind="text:$data.name"></li>
  </ul>
  
 </div>

Much cleaner isnt it? No more hacks, just direct DOM manipulation. That is the power this library gives you. You can write it according to what you prefer.

So that ends my article on how to use templating with KnockoutJS. If you have any queries or feedback, please do leave by a comment which is as always highly appreciated.

Have a nice day everyone!!

Monday, October 28, 2013

Getting knocked out

Everyone is saying JavaScript is the future and i was wondering what all the hype was. Was never a big fan of JavaScript to begin with since i was involved mainly with writing back-end code. But i am always open for new things and being the enthusiast i am, thought to try out one of the plethora of JavaScript libraries out there.

Since MVC knowledge is inherent in anyone who would have written any serious web application, i wanted to try out something closer to my comfort zone. This is where i stumbled upon knockoutjs . It advocates more of a MVVM(Model-View-View-Model) architectural pattern which i believe is a very handy way to handle your front-end logic with a clear layer of separation.

I remember the code we wrote prior to these libraries where we used a separate JSON array for each page to hold all the elements in that page and do all validations based on the attributes we define on each JSON attribute.

With Knockout, this is all handled by the library. It handles the data bindings to the elements, changes to the elements as well dependency tracking. I did some reconnaissance of my own on the library and this article is just an introduction to what you can achieve with this library.

The code is simple, i enter my first name and last name and i have a separate field that displays the full name by concatenating the first name and the last name. Then i have a simple button to generate the JSON string which we could use to send the data back to the server.

Let us look at the code;

 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
 <title>Personal Information</title>
</head>

<body>

 <div>
  <table>
   <tr>
    <td>First Name : </td>
    <td><input type="text" name="txtName" id="txtName" data-bind="value:firstname,valueUpdate:'afterkeydown'"></td>
   </tr>
   
   <tr>
    <td>Last Name : </td>
    <td><input type="text" name="txtLName" id="txtLName" data-bind="value:lastname,valueUpdate:'afterkeydown'"></td>
   </tr>
   
   <tr>
    <td colspan="2"><span id="lblFullName" data-bind="text:fullname"></span></td>
   </tr>
   
   <tr>
    <td colspan="2"><button data-bind="click: generateJSON">Generate JSON String</button></td>
   </tr>
  </table>
 </div>

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>

 <script type="text/javascript">
 
 $(function(){
   var person = {
    firstname:ko.observable(''),
    lastname:ko.observable(''),
    generateJSON:function(){
     alert(ko.toJSON(person));
    }
   };
   
   person.fullname = ko.computed(function(){
    
    return "The full name is : "+this.firstname()+" "+this.lastname();
   },person);
  
   ko.applyBindings(person);
  
  }
  );
 </script>
</body>
</html>

As you can see from the code this is just a normal HTML mark-up. The magic happens within the code between the script tags. For ease of use of this code i have included the knockout and jquery scripts directly from the CDN locations because otherwise you would have to manually download them and include the scripts.

In Knockout, everything revolves around your Model. This is the main point of interaction in terms of Knockout. Here i have defined by model as person. One thing to note is that i have defined the firstname and lastname properties as observable. In Knockout, observables are JavaScript functions since not all browsers support getters/setters.

Then i need to tell how to map each property in my model to the DOM elements. This is done through the data-bind attribute. As you can see, in each input element, i have defined the data-bind attribute and stated that the value property should be equal to the value of the property in my Model.

Knockout also has a concept called computed observables which was previously called Dependent-Observables. What this does is that it allows me to aggregate any fields within the model and show them as part of the result as well and any change in the properties will be reflected in the computed observable variable as well. You can see that if you keep typing values to the firstname and last name input boxes, the full name string also changes accordingly. I have specified another value in the data-bind attribute as valueUpdate:'afterkeydown' which allows the changes typed into the input boxes to be reflected as the user types in which otherwise would only have reflected if the user tabs into the fields.

To bind our Model to the Knockout library, we call ko.applyBindings passing in our Model. There are helper methods that allow us to generate a JSON string of our model which is what i have done in the click event function defined within my Model.

I hope this introduction would get you interested to try this library out if you have not already. I will follow up this post with more advanced topics such as templating, observable arrays, parent binding context etc..

As always your comments and suggestions are most welcome.