11 min read

(For more resources related to this topic, see here.)

Backbone.js is a lightweight JavaScript framework that is based on the Model-View-Controller (MVC) pattern and allows developers to create single-page web applications. With Backbone, it is possible to update a web page quickly using the REST approach with a minimal amount of data transferred between a client and a server. Backbone.js is becoming more popular day by day and is being used on a large scale for web applications and IT startups; some of them are as follows:

  • Groupon Now!: The team decided that their first product would be AJAX-heavy but should still be linkable and shareable. Though they were completely new to Backbone, they found that its learning curve was incredibly quick, so they were able to deliver the working product in just two weeks.
  • Foursquare: This used the Backbone.js library to create model classes for the entities in foursquare (for example, venues, check-ins, and users). They found that Backbone’s model classes provide a simple and light-weight mechanism to capture an object’s data and state, complete with the semantics of a classical inheritance.
  • LinkedIn mobile: This used Backbone.js to create its next-generation HTML5 mobile web app. Backbone made it easy to keep the app modular, organized, and extensible, so it was possible to program the complexities of LinkedIn’s user experience. Moreover, they are using the same code base in their mobile applications for iOS and Android platforms.
  • WordPress.com: This is a SaaS version of WordPress and uses Backbone.js models, collections, and views in its notification system, and is integrating Backbone.js into the Stats tab and into other features throughout the home page.
  • Airbnb: This is a community marketplace for users to list, discover, and book unique spaces around the world. Its development team has used Backbone in many latest products. Recently, they rebuilt a mobile website with Backbone.js and Node.js tied together with a library named Rendr.

You can visit the following links to get acquainted with other usage examples of Backbone.js:

http://backbonejs.org/#examples

Backbone.js was started by Jeremy Ashkenas from DocumentCloud in 2010 and is now being used and improved by lots of developers all over the world using Git, the distributed version control system.

In this article, we are going to provide some practical examples of how to use Backbone.js, and we will structure a design for a program named Billing Application by following the MVC and Backbone pattern. Reading this article is especially useful if you are new to developing with Backbone.js.

Designing an application with the MVC pattern

MVC is a design pattern that is widely used in user-facing software, such as web applications. It is intended for splitting data and representing it in a way that makes it convenient for user interaction. To understand what it does, understand the following:

  • Model: This contains data and provides business logic used to run the application
  • View: This presents the model to the user
  • Controller: This reacts to user input by updating the model and the view

There could be some differences in the MVC implementation, but in general it conforms to the following scheme:

Worldwide practice shows that the use of the MVC pattern provides various benefits to the developer:

  • Following the separation of the concerned paradigm, which splits an application into independent parts, it is easier to modify or replace
  • It achieves code reusability by rendering a model in different views without the need to implement model functionality in each view
  • It requires less training and has a quicker startup time for the new developers within an organization

To have a better understanding of the MVC pattern, we are going to design a Billing Application. We will refer to this design throughout the book when we are learning specific topics.

Our Billing Application will allow users to generate invoices, manage them, and send them to clients. According to the worldwide practice, the invoice should contain a reference number, date, information about the buyer and seller, bank account details, a list of provided products or services, and an invoice sum. Let’s have a look at the following screenshot to understand how an invoice appears:

How to do it…

Let’s follow the ensuing steps to design an MVC structure for the Billing Application:

  1. Let’s write down a list of functional requirements for this application. We assume that the end user may want to be able to do the following:
    • Generate an invoice
    • E-mail the invoice to the buyer
    • Print the invoice
    • See a list of existing invoices
    • Manage invoices (create, read, update, and delete)
    • Update an invoice status (draft, issued, paid, and canceled)
    • View a yearly income graph and other reports
  2. To simplify the process of creating multiple invoices, the user may want to manage information about buyers and his personal details in the specific part of the application before he/she creates an invoice. So, our application should provide additional functionalities to the end user, such as the following:
    • The ability to see a list of buyers and use it when generating an invoice
    • The ability to manage buyers (create, read, update, and delete)
    • The ability to see a list of bank accounts and use it when generating an invoice
    • The ability to manage his/her own bank accounts (create, read, update, and delete)
    • The ability to edit personal details and use them when generating an invoice

    Of course, we may want to have more functions, but this is enough for demonstrating how to design an application using the MVC pattern.

  3. Next, we architect an application using the MVC pattern.

    After we have defined the features of our application, we need to understand what is more related to the model (business logic) and what is more related to the view (presentation). Let’s split the functionality into several parts.

  4. Then, we learn how to define models.

    Models present data and provide data-specific business logic. Models can be related to each other. In our case, they are as follows:

    • InvoiceModel
    • InvoiceItemModel
    • BuyerModel
    • SellerModel
    • BankAccountModel
  5. Then, will define collections of models.

    Our application allows users to operate on a number of models, so they need to be organized into a special iterable object named Collection. We need the following collections:

    • InvoiceCollection
    • InvoiceItemCollection
    • BuyerCollection
    • BankAccountCollection
  6. Next, we define views.

    Views present a model or a collection to the application user. A single model or collection can be rendered to be used by multiple views. The views that we need in our application are as follows:

    • EditInvoiceFormView
    • InvoicePageView
    • InvoiceListView
    • PrintInvoicePageView
    • EmailInvoiceFormView
    • YearlyIncomeGraphView
    • EditBuyerFormView
    • BuyerPageView
    • BuyerListView
    • EditBankAccountFormView
    • BankAccountPageView
    • BankAccountListView
    • EditSellerInfoFormView
    • ViewSellectInfoPageView
    • ConfirmationDialogView
  7. Finally, we define a controller.

    A controller allows users to interact with an application. In MVC, each view can have a different controller that is used to do following:

    • Map a URL to a specific view
    • Fetch models from a server
    • Show and hide views
    • Handle user input

Defining business logic with models and collections

Now, it is time to design business logic for the Billing Application using the MVC and OOP approaches.

In this recipe, we are going to define an internal structure for our application with model and collection objects. Although a model represents a single object, a collection is a set of models that can be iterated, filtered, and sorted.

Relations between models and collections in the Billing Application conform to the following scheme:

How to do it…

For each model, we are going to create two tables: one for properties and another for methods:

  1. We define BuyerModel properties.

    Name

    Type

    Required

    Unique

    id

    Integer

    Yes

    Yes

    name

    Text

    Yes

     

    address

    Text

    Yes

     

    phoneNumber

    Text

    No

     

  2. Then, we define SellerModel properties.

    Name

    Type

    Required

    Unique

    id

    Integer

    Yes

    Yes

    name

    Text

    Yes

     

    address

    Text

    Yes

     

    phoneNumber

    Text

    No

     

    taxDetails

    Text

    Yes

     

  3. After this, we define BankAccountModel properties.

    Name

    Type

    Required

    Unique

    id

    Integer

    Yes

    Yes

    beneficiary

    Text

    Yes

     

    beneficiaryAccount

    Text

    Yes

     

    bank

    Text

    No

     

    SWIFT

    Text

    Yes

     

    specialInstructions

    Text

    No

     

  4. We define InvoiceItemModel properties.

    Name

    Arguments

    Return Type

    Unique

    calculateAmount

    Decimal

     

  5. Next, we define InvoiceItemModel methods.

    We don’t need to store the item amount in the model, because it always depends on the price and the quantity, so it can be calculated.

    Name

    Type

    Required

    Unique

    id

    Integer

    Yes

    Yes

    deliveryDate

    Date

    Yes

     

    description

    Text

    Yes

     

    price

    Decimal

    Yes

     

    quantity

    Decimal

    Yes

     

  6. Now, we define InvoiceModel properties.

    Name

    Type

    Required

    Unique

    id

    Integer

    Yes

    Yes

    referenceNumber

    Text

    Yes

     

    date

    Date

    Yes

     

    bankAccount

    Reference

    Yes

     

    items

    Collection

    Yes

     

    comments

    Text

    No

     

    status

    Integer

    Yes

     

  7. We define InvoiceModel methods.

    The invoice amount can easily be calculated as the sum of invoice item amounts.

    Name

    Arguments

    Return Type

    Unique

    calculateAmount

     

    Decimal

     

  8. Finally, we define collections.

    In our case, they are InvoiceCollection, InvoiceItemCollection, BuyerCollection, and BankAccountCollection. They are used to store models of an appropriate type and provide some methods to add/remove models to/from the collections.

How it works…

Models in Backbone.js are implemented by extending Backbone.Model, and collections are made by extending Backbone.Collection. To implement relations between models and collections, we can use special Backbone extensions.

To learn more about object properties, methods, and OOP programming in JavaScript, you can refer to the following resource:

https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript

Modeling an application’s behavior with views and a router

Unlike traditional MVC frameworks, Backbone does not provide any distinct object that implements controller functionality. Instead, the controller is diffused between Backbone.Router and Backbone. View and the following is done:

  • A router handles URL changes and delegates application flow to a view. Typically, the router fetches a model from the storage asynchronously. When the model is fetched, it triggers a view update.
  • A view listens to DOM events and either updates a model or navigates an application through a router.

The following diagram shows a typical workflow in a Backbone application:

How to do it…

Let’s follow the ensuing steps to understand how to define basic views and a router in our application:

  1. First, we need to create wireframes for an application.

    Let’s draw a couple of wireframes in this recipe:

    • The Edit Invoice page allows users to select a buyer, to select the seller’s bank account from the lists, to enter the invoice’s date and a reference number, and to build a table of shipped products and services.

    • The Preview Invoice page shows how the final invoice will be seen by a buyer. This display should render all the information we have entered in the Edit Invoice form. Buyer and seller information can be looked up in the application storage. The user has the option to either go back to the Edit display or save this invoice.

  2. Then, we will define view objects.

    According to the previous wireframes, we need to have two main views: EditInvoiceFormView and PreviewInvoicePageView. These views will operate with InvoiceModel; it refers to other objects, such as BankAccountModel and InvoiceItemCollection.

  3. Now, we will split views into subviews.

    For each item in the Products or Services table, we may want to recalculate the Amount field depending on what the user enters in the Price and Quantity fields. The first way to do this is to re-render the entire view when the user changes the value in the table; however, it is not an efficient way, and it takes a significant amount of computer power to do this.

    We don’t need to re-render the entire view if we want to update a small part of it. It is better to split the big view into different, independent pieces, such as subviews, that are able to render only a specific part of the big view. In our case, we can have the following views:

    As we can see, EditInvoiceItemTableView and PreviewInvoiceItemTableView render InvoiceItemCollection with the help of the additional views EditInvoiceItemView and PreviewInvoiceItemView that render InvoiceItemModel. Such separation allows us to re-render an item inside a collection when it is changed.

  4. Finally, we will define URL paths that will be associated with a corresponding view. In our case, we can have several URLs to show different views, for example:
    • /invoice/add
    • /invoice/:id/edit
    • /invoice/:id/preview

Here, we assume that the Edit Invoice view can be used for either creating a new invoice or editing an existing one. In the router implementation, we can load this view and show it on specific URLs.

How it works…

The Backbone.View object can be extended to create our own view that will render model data. In a view, we can define handlers to user actions, such as data input and keyboard or mouse events.

In the application, we can have a single Backbone.Router object that allows users to navigate through an application by changing the URL in the address bar of the browser. The router object contains a list of available URLs and callbacks. In a callback function, we can trigger the rendering of a specific view associated with a URL.

If we want a user to be able to jump from one view to another, we may want him/her to either click on regular HTML links associated with a view or navigate to an application programmatically.


Subscribe to the weekly Packt Hub newsletter. We'll send you this year's Skill Up Developer Skills Report.

* indicates required

LEAVE A REPLY

Please enter your comment!
Please enter your name here