• A sample with Backbone.js main set of features

    Published by mkrikorian on June 27th, 2012 3:31 pm under Backbone, Javascript, MVC, Underscore

    No Comments

    Lately I had the chance to read/learn about the main features of Backbone.js and I decided to code a sample page containing most of them. The framework is pretty straightforward to use and seems to be very powerful. Among the stuff you can do very easily the one that I liked most is the synchronization of models between the client and the server and how you can override or extend this capability. It also provides an MVC-like pattern that helps you to modularize and organize your client code better and make it more maintainable. Besides the framework lacks of UI templating capabilities this help it to not be intrusive in the HTML markup as other frameworks with these features do (for example handlebars on Ember.js); Backbone manifests that it gives you the freedom to select the templating framework you prefer. It also does not perform automatic refreshing when a model value change (like Ember.js does) but you can achieve this behavior by setting bindings over the desired properties and trigger view’s refresh explicitly.

    So I’ve created a sample HTML and JS containing most of the main features provided by Backbone. The sample shows you how you can organize your client code taking advantage of Backbone.js routers and how you can synchronize model changes with your app server performing operations like retrieve, create and update instances.

    The set of features shown by the example are:

    • MVC-like pattern features and usage example (Routers/Views/Models)
    • Backbone.js models and classes: inheritance & extension
    • Event binding (to trigger particular actions when something happened)
    • Backbone.sync overriding (to handle client-server model synchronization)
    • Model collections and Underscore.js functionallity
    • Model synchronization features: fetching/saving changes
    • Backbone.js navigation capabilities (relying on routers’ routes)

    The HTML page contains basically four sections:

    • First at all, and above the navigation buttons, a text area logs all the synchronization calls Backbone is performing to keep models up to date (this log triggers when Backbone.Sync is called and it’s only for understanding purposes)
    • A section that contains a Backbone view displaying a list of persons (server data) when a particular route is hit (taking advantage of routers [controllers])
    • A section where you can add a new person and, because it uses a collection particular method, it’s synchronized (i.e. created) with the server by a call triggered by the Backbone’s infrastructure
    • A section where you can edit a person and shows you how to use save() method to sync it back to the server

    Server stuff (repository mock)

    The repository for the app models is implemented by having a global variable in the JS. This repository mock makes the sample auto-contained and allows me to show the Backbone.Sync override behavior that will be described below.

    The ‘server repo’ is implemented as shown here:

    backbone_01

    Server repository (mock)

    Backbone.sync

    This function is Backbone’s hook point for performing synchronization of models between client and server. You can extend and/or override this behavior on your application and all sync requests on the client will trigger your functions. Nevertheless, you can also override it at more granular level within your models (see Backbone.sync doc for further information).

    As I said before, in my implementation I’ve decided to store the server data in a global variable within the JS code (peopleServer) that represents the repository where the ‘server’ stores models. In addition I’ve created several helper functions in order to make the code more readable (making the sync code minimalist).

    You can see below my Backbone.sync implementation:

    backbone_02

    Backbone.sync override

    As you can see the sync() method is calling helper functions to do its job. The implementations for these functions are on the same JS file and you can see them below:

    backbone_03

    Server calls helpers

    The logSyncOperation() call just writes to the text area in the page the operation called by Backbone.js and shows you the model instance that is used as input:

    back_01

    The synchronization log that shows all sync requests

    Models

    I’ve started the sample by defining the models I was going to use. So I’ve extended the Person model from Backbone.Model and the People collection from Backbone.Collection. The last one makes heavy usage of Underscore.js (that must be added as a reference if you want to use collections and their functionalities). Both models are shown below and I’ll show you later how you can easily use functions they contain to sync up with the server:

    backbone_04

    Person and People models implementation

    Routers

    After defining the models I’ve created a router in order to handle the query, add and edit actions. This router is like an MVC controller where you define valid routes your application can handle and activate/deactivate the necessary views within the browser.

    The router I’ve implemented is the one shown below and after the code you can see how is integrated and used by the framework:

    backbone_05

    PeopleController (router) implementation

    As I said before the HTML page contains three sections to interact with the models:

    • At index.html#people is where you can see the list of persons stored in the repository. Each time this view is displayed a server fetch is triggered and the latest server data is shown.

    It works like this:

    back_02

    Navigate to #people triggers the list() function which is showing and fetching the people information from the server. You can see when fetching is successful how the PeopleView is instanced and rendered

    • At index.html#people/add is where you can add a new person to the people’s list stored in the repository. When the new person is added (by using the create() function of the people collection) a server call is triggered to create the person and a bound function is called (i.e. the alert you see).

    It works like this:

    back_03

    When add is clicked the new model is created within the collection by using the create() method and this triggers, after executing the binding associated to the collection, a server call in order to create the new model in the repository

    • And finally, at index.html#people/edit/{id} is where you can edit a person in the people’s list stored in the repository. When the person’s information is changed a save() is triggered in order to sync the update with the server.

    It works like this:

    back_04

    When change is clicked a save() method is called in order to update the model in the server repository

    Views

    To display the people’s list I’ve made use of Backbone views. This is a simple thing to use and it just gives you the possibility to render your model as you want by using the templating framework you wish. I’ve missed the auto-refreshing behavior that other frameworks provide, but you can workaround this by setting a binding over a model’s property to trigger views’ refresh() as needed.

    The basic case is simple (as shown in the example). Here I’ve created a view for displaying a person (it’s fullName()) and another view that calls the PersonView for each item in the collection it handles:

    backbone_06

    PersonView and PeopleView definitions and rendering functions

    Finally, when you want to display your view you must instantiate it with the appropriate parameters and call the render() function:

    backbone_07

    Instatiating and rendering a view on the control that has ‘people-list’ class

    Summary

    I like this framework, and how it handles synchronization of models between client and server, allowing you to override or extend this behavior. This is a very flexible feature that allows you to integrate Backbone.js with almost any platform or backend implementation. It allows you to implement a programming model with the well-known MVC pattern helping you to make your code more readable and maintainable, also letting you to navigate through your site without the need to refresh every page each time making a server request.  The main purpose of this example is showing Backbone.js main features and how you can organize your client-side code taking advantage of the Router-View-Model set. It also shows you how can you write a custom sync handler to integrate Backbone.js with any backend (in this case mocked as a local global variable). I recommend you to browse the Backbone.js page for better understanding and get 100% of it.

    Tags: , , ,

  • Leave a comment

    Your email address will not be published.