Compound.js + Backbone.js + doT.js

I like the minimalist and clean solutions and I always look for something like this… hmm, for example doT.js. It is really cool JS template engine. It is quick and small, and user friendly.

So, the Backbone.js is very popular framework. It is not only MVC framework it even has a nice API and it has good references. I don’t want to introduce it because it has well documentation and you can find on the internet many blog-posts and articles about it.

I created one simple Node.js + Compound.js + Backbone.js + doT.js sample application and I would like to show how easy is build “full” 🙂 MVC applicataion which one is use the MVC on the client and server side too.

Ok. First I generated with Compound.js one new controller.

 compound g controller testbackbone  

then I created routings into the config/routes.js

   //testbackbone controller's routings  
   map.get('testbackbone', 'testbackbone#index');    
   map.post('person_url', 'testbackbone#person_url');    
   map.get('person_load/:id', 'testbackbone#person_load');   

I created new layout into the app/layouts/testbackbone_layout.ejs (the naming is important, because the default layout name is the same as your controller name + “_layout” + file extension)

 <!DOCTYPE html>  
 <html lang="en">  
   <head>  
     <title><%= title %></title>  
     <%- stylesheet_link_tag('bootstrap', 'application', 'bootstrap-responsive') %>  
     <%- javascript_include_tag('http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js', 'bootstrap', 'rails', 'underscore-min', 'backbone-min', 'doT', 'application') %>  
     <%- csrf_meta_tag() %>  
      <style>  
           body {  
                margin: 0;  
                padding: 0;  
           }  
           #mycanvas {  
                display: block;  
                border: 1px solid black;  
           }  
      </style>  
   </head>  
   <body>  
     <div class="container">  
       <% var flash = request.flash('info').pop(); if (flash) { %>  
         <div class="alert alert-info">  
           <a class="close" data-dismiss="alert">×</a>  
           <%- flash %>  
         </div>  
       <% } %>  

       <% flash = request.flash('error').pop(); if (flash) { %>  
         <div class="alert alert-error">  
           <a class="close" data-dismiss="alert">×</a>  
           <%- flash %>  
         </div>  
       <% }; %>  

       <%- body %>  

       <hr />  
       <footer>  
         <p>Blabla</p>  
       </footer>  
     </div>  
   </body>  
 </html>  

this layout will load the JavaScript files but first you shoul download the backbone.js and doT.js and save these to the public/javascripts directory.

Ok, I created the controller methods:

 load('application');  
   
 /**  
  *   
  * testbackbone#index  
  */  
 action('index', function() {  
   console.log(req.params);  
   
   render({  
     title: "testbackbone#index",  
     csrfToken: req.csrfToken  
   });  
 });  
   
   
   
 /**  
  *   
  * testbackbone#simple data saver method  
  */  
 action('person_url', function() {  
   console.log(req.params);  
   
   this.id = req.params.id;  
   send({name: this.name, id: 1});  
 });  
   
   
 /**  
  *   
  * testbackbone#person_load  
  */  
 action('person_load', function() {  
   console.log(req.params.id);  
   if (req.params.id == 100) {  
     send({name: "Wanda", id: 100, age: 20, weight: 120, mobile_number: 555555, email: "test@blabla.com"});  
   } else {  
     send({name: "Joe", id: 1, age: 22, weight: 120, mobile_number: 22222222, email: "test2@blabla.com"});  
   }  
 });  

then I created ejs template:

(The authenticity_token is important because when the Backbone.js use POST method to save data and without this token your request will be forbidden.)

 Test Node+Compound+Backbone+doT 🙂 <br />   
   
 <input type="hidden" id="authenticity_token" value="<%= csrfToken %>" />  
   
 <pre></pre>  
 <script type="text/x-dot-template" id="person_template">  
  <label>Search</label>  
   Name: <input type="text" id="name" value="{{=it.name}}"/><br />  
   Age: <input type="text" id="age" value="{{=it.age}}"/><br />  
   Weight: <input type="text" id="weight" value="{{=it.weight}}"/><br />  
   Mobile number: <input type="text" id="mobile_number" value="{{=it.mobile_number}}"/><br />  
   Email: <input type="text" id="email" value="{{=it.email}}"/><br />  
   
  <input type="button" id="save_button" value="Save" />  
  <input type="button" id="load_button" value="Load" />  
 </script>  
   
 <div id="person_container"></div>  
   
 <%- javascript_include_tag('backbone_model/person_model') %>  
 <%- javascript_include_tag('backbone_view/person_view') %>  
   

… then I created two new directory under the public/javascript directory these two directory will be contain the Backbone.js model and view classes.
…these directory names are “backbone_model” and “backbone_view”.

This is my public directory structure:

mypublicjsdir

So now, the clint side – at first I created Backbone model + collection and view.

The model:

person_model.js:

 /**  
  * Person Model  
  * @type @exp;Backbone@pro;Model@call;extend  
  */  
 var Person = Backbone.Model.extend({  
   // We can pass it default values.  
   defaults: {  
     name: null,  
     age: 0,  
     weight: 0,  
     mobile_number: null,  
     email: null,  
     authenticity_token: $('#authenticity_token').val()  
   },  
   url: function() {  
     return this.id ? '/person_url/' + this.id : '/person_url';  
   }  
 });  

 var PersonCollection = Backbone.Collection.extend({  
   model: Person,  
   url: function() {  
     return this.id ? '/person_load/' + this.id : '/person_load';  
   }  
 });  

The view:

person_view.js:

 /*  
  Person view  
  */  
 (function() {  
   PersonView = Backbone.View.extend({  
     initialize: function() {  
       this.person_collection = new PersonCollection();  
       this.render();  
     },  
     render: function() {  
       //the user ID - it is just sample  
       this.person_collection.id = 1;  
         
       // backbone.js fetch method  
       this.person_collection.fetch({  
         success: function(collection, response) {  
           //doT.js templates  
           var pagefn = doT.template(document.getElementById('person_template').text, undefined);  
           document.getElementById('person_container').innerHTML = pagefn(response);  
         }  
       });  
     },  
     events: {  
       //button events  
       "click #save_button": "doSave",  
       "click #load_button": "doLoad"  
     },  
     doSave: function(event) {  
         
       var pagefn = doT.template(document.getElementById('person_template').text, undefined);  
       console.log(pagefn);  
       //init Person model  
       var newPerson = new Person({  
           
         name: $("#name").val(),  
         age: $("#age").val(),  
         weight: $("#weight").val(),  
         mobile_number: $("#mobile_number").val(),  
         email: $("#email").val()  
       });  
       newPerson.set({isActive: true});  
       newPerson.save();  
     },  
     doLoad: function(event) {  
       //load item by user ID  
       this.person_collection.id = 100;  
       //the backbone.js fetching  
       this.person_collection.fetch({  
         //generating doT.js template  
         success: function(collection, response) {  
           var pagefn = doT.template(document.getElementById('person_template').text, undefined);  
           document.getElementById('person_container').innerHTML = pagefn(response);  
         }  
       });  
     }  
   });  
   
   var person_view = new PersonView({el: $("#person_container")});  
   
 }).call(this);  

I think it is easy. You only call the Backbone.js model’s fetch method and url method and the doT template engine will replace template variables.

The doT template engine is very flexible, for example you can customize its compilation settings.

That’s it. 🙂

Advertisements
This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s