Você está na página 1de 8

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

Bridging the geek-suit divide


Exploringbothbusinessandtechnology

A simple Backbone.Marionette tutorial


Posted on April 15, 2012 by David Sulc

In this series of posts, well cover writing a simple Backbone.js application as a primer. You can see the live result here. The original application is at https://github.com/ddellacosta/backbone.jsexamples/tree/master/collections3 and all design assets (CSS, images, etc.) are from there. This tutorial will show you how to use Derick Baileys Backbone.Marionette to build a simple application. But beyond getting a simple walkthrough, youll also be able to compare the app we write to the original, and see how Backbone.Marionette makes your life easier when writing Backbone apps. So whats the app going to be? It will simply allow cats to be ranked within a list: click up the cat is more popular, click down, the cat is less popular. Simple, no? Besides, on the internet, everybody likes cats ;-) If you want to skip ahead and checkout the code, its on Github and you can see it in action on this jsFiddle (the image assets have been replaced with placeholders). You can also follow along by checking out out each git commit.Update(June2013): Ive written a book on Marionette. It guides you through developing a complete Marionette application, and will teach you how to structure your code so large apps remain manageable. Also, since this tutorial was written, Marionette has evolved with new functionality and better techniques to write scalable javascript apps. These are naturally covered in the book.

First steps
Since this is a tutorial, well start with all the necessary static assets already in place (CSS, libraries, etc.). So go ahead and grab the zipped archive containing all you need to get started, or get the initial commit from github. The first thing well do is include our application within a javascript file that we include in index.html. Within that file, well start a Backbone.Marionette application, and add a region to it (code): 1 2 3 4 5 M y A p p=n e wB a c k b o n e . M a r i o n e t t e . A p p l i c a t i o n ( ) ; M y A p p . a d d R e g i o n s ( { m a i n R e g i o n :" # c o n t e n t " } ) ;

This region corresponds to an area that we will use in our application. Since our application is simple, well be using only one. However, more complex apps will be able to use multiple regions to better breakdown the applications complexity, using e.g. one region for the navigation menu, another for the main content, etc. The way we set the region is by passing a jQuery selector to the area we want to use. In this particular example, we want to use the DOM element with id content (which you can see in the index.html).
http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/ 1/8

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

So now that we have a region to display things, what are we going to display? I mentioned it earlier: a leader board for cats. Which means were going to need to store information about cats, but also that were going to be dealing with multiple cats

Models and collections


Backbone was designed mainly to build RESTful javascript apps, and it follows this RESTful architecture on the front end: were going to store our cats in Backbone models. Although were not going to be communicating with a server in our case, Backbone provides handy mechanisms to store model modifications on the server: Backbone.sync allows you to (e.g.) call cat.save() and the cats JSON representation will be sent to the server for storage. So what do these models look like? Well, lets go ahead and create a model for our cat (code): 1 A n g r y C a t=B a c k b o n e . M o d e l . e x t e n d ( { } ) ;

The code is deceptively simple: all we need to do is extend a Backbone class, and we get lots of goodies for free As you can see, when you extend a Backbone Model, you need to provide a javascript object. For now, were simply providing an empty object with {}. Remember how were going to deal with multiple cats? Well need some construct to deal with that, and thats where Backbone collections come in. Collections also provide many niceties, some of which well cover later. Lets write the collection to store all of our cats (code): 1 2 3 A n g r y C a t s=B a c k b o n e . C o l l e c t i o n . e x t e n d ( { m o d e l :A n g r y C a t } ) ;

This time youll notice that we didnt simply provide an empty object when extending Backbones Collection. The reason is that a Backbone collection needs to know what king of models it contains. In our case, the collection contains cats, so all we need to do is declare our AngryCat model within the object we use to extend. Now that we have everything in place to start managing our cats, we still need to display them.

Views
What are views in Backbone? Well, for starters, theyre very different from what you might have encountered in other frameworks (such as Rails). In Rails, views simply generate HTML that gets sent to the client. In Backbone, we use template for that role, and views act more like observers: they monitor changes in the applications state (data changes to models, user interactions, etc.) and update the view accordingly. The only view mechanism Backbone provides is the plain vanilla Backbone.View. Backbone.Marionette, on the other, provides several different view types to choose from. Since we want to display a collection of cats, we are going to use Backbone.Marionettes CompositeView and ItemView. Ill briefly cover both of them, but Derick Bailey (Backbone.Marionettes author) covers devoted a blog post to the topic.

Backbone.Marionette.ItemView
http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/ 2/8

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

The item view is, according to the documentation, a view that represents a single item. In our case, well use it to represent a single cat in our collection. Since were going to display all of our cats within a table, this item view will essentially render a table row.

Backbone.Marionette.CompositeView
Were going to use this view to render our collection. We already have an ItemView to render a single cat, so this view will render the table (headers, etc.) and then add one row for each cat in the collection by rendering the ItemView. Backbone.Marionette does a lot behind the scenes for us. By using the composite view to render the collection, we dont need to worry about updating the view when our collection changes (if we add a model instance, for example): the CompositeView does that on its own. It youve glanced at the docs, you might have noticed the Backbone.Marionette also provides a CollectionView. If were going to display a collection, why not use that? Well, the simple answer is that the collection view is designed to simply render the collection (i.e. render one ItemView per model), without any fluff. We want to go slightly further, since we want the collection to have surrounding HTML (namely the table tags, headers, etc.). So now we know what were going to use to display our collection. But how are we going to generate the HTML proper?

Templates
To generate HTML, Backbone uses templates: HTML skeletons that we will fill in with data from a model (e.g.). Templates would be the Backbone equivalent to the views Rails uses. Lets start with the template for the entire collection, which will be a table (code): 1 2 3 4 5 6 7 8 9 < s c r i p tt y p e = " t e x t / t e m p l a t e "i d = " a n g r y _ c a t s t e m p l a t e " > < t h e a d > < t rc l a s s = ' h e a d e r ' > < t h > N a m e < / t h > < / t r > < / t h e a d > < t b o d y > < / t b o d y > < / s c r i p t >

You can see that this template is simply put within the HTML body using a script tag that has a content-type of text/template. The reason for doing so is that the DOM element will be easily selectable using jQuery (which is why the template has an id), but the content-type prevents the browser from doing anything with it. This template will enable us to have a table with a single column containing the cats name. So now, we can move on to writing the template used to create individual rows (code): 1 2 3 < s c r i p tt y p e = " t e x t / t e m p l a t e "i d = " a n g r y _ c a t t e m p l a t e " > < t d > < % =n a m e> < / t d > < / s c r i p t >
3/8

http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

Same concept here as above: a script tag with an id and a special content-type. The addition you see here are the <%= %> tags which will be familiar if youve used ERB before: they interpret the code between them. In this case, were simply going to print the name attribute of the model that is passed to the template. Now that we have our templates, lets write the view code that uses them.

Back to views
First, well write the ItemView that will display a single cat (code): 1 2 3 4 5 A n g r y C a t V i e w=B a c k b o n e . M a r i o n e t t e . I t e m V i e w . e x t e n d ( { t e m p l a t e :" # a n g r y _ c a t t e m p l a t e " , t a g N a m e :' t r ' , c l a s s N a m e :' a n g r y _ c a t ' } ) ;

We need to specify a few things when declaring the ItemView. First, which template were going to use (which is a mandatory requirement). Then, we can specify some (optional) properties to control the HTML that gets rendered. At this point, lets take a small break to Backbones rendering. When a view is rendered, Backbone will create a DOM element that you can then manually insert into the document. If you look at a few Backbone tutorials, youll typically see that at work in a views render method. Backbone.Marionette does a lot of cool things for us, and as a consequence our ItemView doesnt have a render method visible. In other words, we havent had to declare a render method, because Backbone.Marionette already does that for us, and the created DOM element will get added to the document with our CompositeView. So now that you know some of what goes on when a Backbone view gets rendered, the next properties will make more sense to you. The className is simply an HTML class that gets added to the element Backbone creates, so our item will have class=angry_cat in its HTML tag. Speaking of the HTML tag, the plain vanilla tag the Backbone uses when creating an element during a view render is a div. Since were going to display our cats within a table, that wouldnt suit our needs: we need a tr tag to be generated as the DOM element instead, and that is what we demand with the tagName property. Now, onto the CompositeView (code): 1 2 3 4 5 6 7 8 9 1 0 1 1 A n g r y C a t s V i e w=B a c k b o n e . M a r i o n e t t e . C o m p o s i t e V i e w . e x t e n d ( { t a g N a m e :" t a b l e " , i d :" a n g r y _ c a t s " , c l a s s N a m e :" t a b l e s t r i p e dt a b l e b o r d e r e d " , t e m p l a t e :" # a n g r y _ c a t s t e m p l a t e " , i t e m V i e w :A n g r y C a t V i e w , a p p e n d H t m l :f u n c t i o n ( c o l l e c t i o n V i e w ,i t e m V i e w ) { c o l l e c t i o n V i e w . $ ( " t b o d y " ) . a p p e n d ( i t e m V i e w . e l ) ; } } ) ;
4/8

http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

The same properties are being defined as for the ItemView, with the addition of itemView. Since our CompositeView will be rendering a collection, we are telling it which ItemView to use to render each model within the collection. In addition, since we arent just going to be dumping the generated HTML at the end fo the template, but in the middle, we have to specify how HTML should be instered into our template with the appendHtml function. As you can tell, were not asking for much: we just want it dumped within the tbody. UPDATE: Since writing this post, Marionnette has been updated, and the CompositeViews behavior has changed slightly. You now need to the view to rerender the portion displaying the collection when the latter is sorted. See this commit. Now that we have templates and views defined, lets display something already!

Initializers
Right after we start our app, well want to have our list of cats displayed. For this purpose, well add a simple initializer (code): 1 2 3 4 5 6 M y A p p . a d d I n i t i a l i z e r ( f u n c t i o n ( o p t i o n s ) { v a ra n g r y C a t s V i e w=n e wA n g r y C a t s V i e w ( { c o l l e c t i o n :o p t i o n s . c a t s } ) ; M y A p p . m a i n R e g i o n . s h o w ( a n g r y C a t s V i e w ) ; } ) ;

This initializer will receive any options we send to our application when we call its start method (which we havent done yet). What our initializer does is straightforward: create a new view with our cats, and display it.

Starting the application


Pretty straightforward also (code): 1 2 3 4 5 6 7 8 9 $ ( d o c u m e n t ) . r e a d y ( f u n c t i o n ( ) { v a rc a t s=n e wA n g r y C a t s ( [ {n a m e :' W e tC a t '} , {n a m e :' B i t e yC a t '} , {n a m e :' S u r p r i s e dC a t '} ] ) ; M y A p p . s t a r t ( { c a t s :c a t s } ) ; } ) ;

Once the DOM is ready, we create a collection of cats populated by cat models we create simultaneously. Then, we simply start our application by passing in the cats collection, and voil! The first milestone for our leader board is done (and should look something like this): we can display a list of models. Nows a good time for a break, but in the next post, well add functionality to this (momentarily) boring app.
This entry was posted in Backbone.js, Backbone.Marionette. Bookmark the permalink.

http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/

5/8

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

12 Responses to A simple Backbone.Marionette tutorial


ChrisHoffman says:
April 18, 2012 at 11:29 am

Awesome post. Cant wait for the next one, where you hopefully go into event binding.

david says:
April 18, 2012 at 12:26 pm

Yup, the next installment will cover event binding :-)

JohannesHiemer says:
April 24, 2012 at 11:28 am

Great post. Perhaps a small side note. I am currently a beginner with BbMarionette and I was a bit confused where to put the template stuff, because from other projects I always knew that there was a separate template folder. Now I see you put it into the index.html. Are you going to split things up in later parts of the tutorial? What would be interesting for me as well, would be some kind of subrouting and modularization for e.g. cats, dogs and so.

Tres says:
April 26, 2012 at 3:11 pm

Not much of an improvement compared to plain backbone and much less understandable.

david says:
April 27, 2012 at 2:54 am

@Tres I disagree. Although a simple example doesnt highlight Marionettes advantages, I find it does make Backbone development simpler. For example, using only Backbone, how would you manage redisplaying the cats in the proper order when their rank changes? You could listen to changes to the collection and rerender the list, but it would mean writing boiler plate code that Marionette provides for free. In other words, I find Marionette makes it much easier and cleaner. In addition, having a CollectionView display your items means you dont have to write more boiler plate code to display new items, rerender modified items, removed deleted items, etc Initializers are also great when you need to fetch data from the server in the background while your application starts up (e.g. a list of categories), and Marionette routers (which I havent covered yet) are perfect for progressive enhancement. Are there any specific sections in this post you find confusing? Or is it just the framework? Much like generating a simple about me page with Rails would probably make someone think this sucks, PHP makes outputting text really easy, Ill use that, I agree that the app in this post is very basic and doesnt fully leverage Marionette, but I wanted something really simple for beginners. Naturally, if youre just building a trivial site, it might not be worth including Marionette. That said, Ive also rewritten the example at http://www.atinux.fr/backbone-books/ to use Backbone.Marionette. Im going to do a writeup soon, and that will propably be a better showcase of how Marionette helps with managing complex
http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/ 6/8

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

Backbone applications.

david says:
April 27, 2012 at 3:00 am

@Johannes Yes, you could put the templates in a separate folder also. Routing and such will be covered in another tutorial, that will cover the rewriting of this exmaple: http://www.atinux.fr/backbone-books/ In the meantime, you can see how Derick Bailey (Marionettes creator) manages mulitple sub apps with Marionette routing/modularization: https://github.com/derickbailey/bbclonemail

Charles says:
April 27, 2012 at 12:53 pm

Nice tutorial :) Could you make an example for using all this in a bigger environment? I mean using different modules with loose dependencies. Im asking because I read about some patterns for bigger javascript applications and there the mediator pattern was described so modules will not communicate directly but over the mediator. Now Im asking myself if this backbone.marionette event aggregator is the same as this mediator and if it could be used for managing multiple modules.

david says:
April 30, 2012 at 2:50 am

Yes, Ive rewritten and expanded http://www.atinux.fr/backbone-books/ to use as an example, and will write up a tutorial on the subject soon. In the meanitme, if you just want to see the code for a larger app, you can look at https://github.com/derickbailey/bbclonemail which was written by Derick Bailey (Marionettes author) as an example app to showcase Marionette. To answer your question more directly, the event aggregator is used as a mediator. In the second part of this tutorial (http://davidsulc.com/blog/2012/04/22/a-simple-backbone-marionette-tutorial-part-2/), you use events to trigger rank changes in the collection. Since this is implemented using the event aggregator, the different objects remain loosely coupled. If you want to compare with an example that doesnt use a mediator, you can look at the original source code here: https://github.com/ddellacosta/backbone.js-examples/tree/master/collections3 So hang on, and soon youll have a brand new tutorial to dig into ;-)

Joakim says:
May 5, 2012 at 8:57 am

Now this is very good tutorial. It would be perfect if there was instructions how to use fetch with this to get the data wich is is always little trickier due to async nature. I have created app where Views and collection are setup just like in this tutorial
http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/ 7/8

1/16/2014

A simple Backbone.Marionette tutorial | Bridging the geek-suit divide

and otherwise its like bbclonemail.contactsapp.js + bbclonemail other structure What should be put in to xxs.showXXX = function(){ } and what goes to yyy.addInitializer The problem is that if you want to load and refresh the data from server and rerender how to do it? It gets updated only after second call to showXX(I put collection rerender to fetch succes to corret this, is this correct approach?) Another issues is that if you navigate directly to the url which routes to app in question then its shows every item twice, allthough showXXX is called only once and data also is fethced once, however if you come from another app everything is working fine.

david says:
May 6, 2012 at 7:02 am

Youll probably want to check out my new tutorial, which is more advanced and covers fetching data. Read about it here: http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/ Another way to solve issues with views being displayed before data has been fetched is to use collections that trigger callbacks. Derick Bailey does that in BBCloneMail: he creates a special collection type that triggers callbacks (https://github.com/derickbailey/bbclonemail/blob/master/public/javascripts/bbclonemail.collection.js) and then he creates callbacks on the controller actions that can get triggered and need to display data before it might be ready (see https://github.com/derickbailey/bbclonemail/blob/master/public/javascripts/mail/bbclonemail.mailapp.js#L73-80) Hope this helps !

david says:
May 7, 2012 at 5:20 am

@Charles The new tutorial is up at http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/ It covers writing a bigger app, and using sub apps to swap out functionality in a loosely coupled way (among others).

Pingback: SkeletonofaJavaScriptwebapplicationhoneysoft

Bridging the geek-suit divide


ProudlypoweredbyWordPress.

http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/

8/8

Você também pode gostar