Technology

An introduction to Backbone, a frontend framework

Posted by Pixafy Team

Many frontend developers might face code management problems when they are working on a huge web application that has a page containing lots of features without refreshing the page.  Backbone is a great framework for them to separate the model, view and router.  As most developers know that pattern, they could make code to be much easier to maintain in the future.

One of the great things about backbone is the localized router. It means we can change the fragment at the end of the URL to render different views without refreshing a page.   The Following Example requires jQuery.js, Backbone.js and Underscore.js.

Create a view

Benefit: If the view changes, the model is going to be updated as well.

var SampleView=Backbone.View.extend({
				template:_.template($("#sample-template").html()),
				//event listeners for dom elements
				events:{
					"blur #firstname" 		:	"blurFirstname",
					"blur #lastname" 		:	"blurLastname",
					"click #firstname-label"	:	"clickFirstname",
					"click #lastname-label"	:	"clickLastname",
				},
				initialize:function(args)
				{
					this.model=args.model;
					this.router=args.router;
//change the view when model has been changed
					this.model.on("change", this.render, this);
},
				//function for rendering html
				render:function()
				{
					var data=this.model.toJSON();
					this.$el.html(this.template(data));
				},

				//events
				blurFirstname:function(ele){
					this.model.set("firstname",$(ele.target).val());
					this.router.navigate("",{trigger:true});
				},
				blurLastname:function(ele){
					this.model.set("lastname",$(ele.target).val());
					this.router.navigate("",{trigger:true});
				},
				clickFirstname:function(ele){
					this.router.navigate("firstname.edit",{trigger:true});
				},
				clickLastname:function(ele){
					this.router.navigate("lastname.edit",{trigger:true});
				},
			});

After having the view object, we also need a template for rendering. In this case, I put the template inside a script. In this way, it won’t display any content to the visitor before rendering. As you can see below, there is some javascript, a nice feature that comes from form Underscore.js.  Code inside <% %> tag is in the Javascript syntax.

<script id="sample-template" type="text/html">
	<table border='1'>
		<tr>
			<td>Firstname:</td>
		<td>
		<% if ( editFirstname ==true ) {%>
			<input  id="firstname" value="<%= firstname %>" type="text" autofocus="autofocus"/>
		<% }else{ %>
			<div id="firstname-label"><%= firstname %></div>
<% } %>
	</td>
	</tr>
	<tr>
		<td>Lastname:</td>
		<td>
<% if ( editLastname ==true) { %>
		<input  id="lastname" value="<%= lastname %>" type="text" autofocus="autofocus"/>
		<% }else{ %>
<div id="lastname-label"><%= lastname %><div>
		<% } %>
	</td>
	</tr>
	</table>
</script>

Create a model

As with other MVC frameworks, Backbone also has its model, which handles logic and holds data.

Benefit: If the model changes, the view will be changed as well.

var SampleModel=Backbone.Model.extend({
				defaults:{
					firstname:"Tom",
					lastname:"Lee",
					editFirstname:false,
					editLastname:false
				},
				normalMode:function()
				{
					var self=this;
					self.set('editFirstname',false);
					self.set('editLastname',false);
				},
				editFirstname:function()
				{
					var self=this;
					self.set('editFirstname',true);
					self.set('editLastname',false);
				},
				editLastname:function()
				{
					var self=this;
					self.set('editFirstname',false);
					self.set('editLastname',true);
				}
			});

Create a router object (the controller)

var SampleRouter = Backbone.Router.extend({
				initialize:function(args)
				{
					this.model=args.model;
				},
				routes: {
					""		: "showDefault",
					"firstname.edit"	: "editFirstname",
					"lastname.edit"	: "editLastname"
				},
				showDefault: function(){
					this.model.normalMode();
				},
				editFirstname: function(){
					this.model.editFirstname();
				},
				editLastname: function(){
					this.model.editLastname();
				}
			  });

After writing all the objects, we need to connect the view, model and controller (router) together in order to make them work.

var model 	= new SampleModel();
var router	= new SampleRouter({model:model});
var view	= new SampleView({model:model,router:router});
$("#view").html(view.$el);
view.render();
Backbone.history.start();

The Result

After connecting the view, model and controller, the page should be able render different views with different fragment.  When you input a new string, the model will be updated. If you want to get what data is in your model, you can use the function model.toJSON();

Without any fragment (backbone.html):

With fragment (backbone.html#firstname.edit)

Conclusion

The benefit for using backbone is being able to separate the view, model and controller (router). Thus, it’s easier for a programmer to manage the code. In addition, we don’t have to take care of the interaction with view and model, like if the model has to be changed because the view did, or vice versa.  There is also another benefit for this. When you hit backspace, the page won’t reload and will just go back to the preview fragment.

Have any questions or comments? Leave us a message below or tweet us @Pixafy!