





















































(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:
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.
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:
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:
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:
Let's follow the ensuing steps to design an MVC structure for the Billing Application:
Of course, we may want to have more functions, but this is enough for demonstrating how to design 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.
Models present data and provide data-specific business logic. Models can be related to each other. In our case, they are as follows:
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:
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:
A controller allows users to interact with an application. In MVC, each view can have a different controller that is used to do following:
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:
For each model, we are going to create two tables: one for properties and another for methods:
We define BuyerModel properties.
Name |
Type |
Required |
Unique |
id |
Integer |
Yes |
Yes |
name |
Text |
Yes |
|
address |
Text |
Yes |
|
phoneNumber |
Text |
No |
|
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 |
|
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 |
|
We define InvoiceItemModel properties.
Name |
Arguments |
Return Type |
Unique |
calculateAmount |
- |
Decimal |
|
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 |
|
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 |
|
The invoice amount can easily be calculated as the sum of invoice item amounts.
Name |
Arguments |
Return Type |
Unique |
calculateAmount |
|
Decimal |
|
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.
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
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:
The following diagram shows a typical workflow in a Backbone application:
Let's follow the ensuing steps to understand how to define basic views and a router in our application:
Let's draw a couple of wireframes in this recipe:
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.
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.
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.
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.