ApplicationA Thorough Introduction To Backbone.Marionette (Part 1)

Advertisement

To help you tap the full potential of Marionette, we’ve prepared an entire eBook1 full of useful hands-on examples which is also available in the Smashing Library2. — Ed.

Backbone.js is quickly becoming the most popular framework for building modular client-side JavaScript applications. This is largely due to its low barrier to entry; getting started with it is super-simple. However, unlike Ember.js, Backbone, being so minimal, also leaves a lot up to the developer to figure out.

So, once you start getting into more advanced applications, it’s no longer so simple. Backbone.Marionette was created to alleviate a lot of the growing pains of Backbone development. Backbone.Marionette “make[s] your Backbone.js apps dance with a composite application architecture!,” according to its author.

This “composite” architecture refers mainly to the numerous view types that have been provided to help with subview management. We won’t be discussing those views today (although we will touch on regions, which are a small part of the subview management that Marionette offers), but you can find documentation for this project in the GitHub repository3. It offers numerous components that extend Backbone and that enable you to write less boilerplate and do more stuff with little to no hassle, especially when it comes to views.

The Central Application Object

Most of the time, when someone creates a Backbone application, they make a central object that everything is attached to, which is often referenced as App or Application. Backbone doesn’t offer anything to make this object from, so most people just create a main router and make that the app object. While it’s great that people are attaching things to a central object so that the global namespace isn’t so convoluted, the router was not designed to handle this task.

Derick Bailey, the creator of Marionette, had a better idea. He created a “class” that you could instantiate an object from that is specifically designed to handle the responsibilities of being the go-to root object of the entire application. You create a new application with var App = new Backbone.Marionette.Application(), and then, when everything is set, you start the application with App.start(options). I’ll discuss the options argument soon. For now, just remember that it’s optional.

Initializers

One of the coolest things about Marionette’s Application is the initializers. When your code is modular, several pieces will need to be initialized when the application starts. Rather than filling a main.js file with a load of code to initialize all of these objects, you can just set the modules up for initialization within the code for the module. You do this using addInitializer. For example:

var SomeModule = function(o){
  // Constructor for SomeModule
};

App.addInitializer(function(options) {
  App.someModule = new SomeModule(options);
});

All of the initializers added this way will be run when App.start is called. Notice the options argument being passed into the initializer. This is the very same object that is passed in when you call App.start(options). This is great for allowing a configuration to be passed in so that every module can use it.

A few events are also fired when running through these initializers:

  • initialize:before
    Fires just before the initializers are run.
  • initialize:after
    Fires just after the initializers have all finished.
  • start
    Fires after initialize:after.

You can listen for these events and exert even more control. Listen for these events like this:

App.on('initialize:before', function(options) {
  options.anotherThing = true; // Add more data to your options
});
App.on('initialize:after', function(options) {
  console.log('Initialization Finished');
});
App.on('start', function(options) {
  Backbone.history.start(); // Great time to do this
});

Pretty simple, and it gives you a ton of flexibility in how you start up your applications.

Event Aggregator

The Application object brings even more possibilities for decoupling a Backbone application through the use of an event aggregator. A while back I wrote a post about scalable JavaScript applications4, in which I mentioned that modules of a system should be completely ignorant of one another, and that the only way they should be able to communicate with each other is through application-wide events. This way, every module that cares can listen for the changes and events they need to so that they can react to them without anything else in the system even realizing it exists.

Marionette makes this kind of decoupling largely possible via the event aggregator that is automatically attached to the application object. While this is only one of the mechanisms that I wrote about in that article, it is a start and can be very useful in even smaller applications.

The event aggregator is available through a property in the application called vent. You can subscribe and unsubscribe to events simply via the on and off methods, respectively (or bind and unbind, if you prefer). These functions might sound familiar, and that’s because the event aggregator is simply an extension of Backbone’s Event object5. Really, the only thing new here that you need to worry about is that we’re using the events on an object that should be accessible everywhere within your app, so that every piece of your application can communicate through it. The event aggregator is available as its own module too, so you can add it to any object you want, just like Backbone’s Event.

Regions

Region is another module for Marionette that enables you to easily attach views to different regions of an HTML document. I won’t go into detail about how regions work here — that’s a topic for another day — but I’ll cover it briefly and explain how to use them with Application.

A region is an object — usually created with new Backbone.Marionette.Region({ el: 'selector'}) — that manages an area where you attach a view. You would add a view and automatically render it by using show. You can then close out that view (meaning it will remove it from the DOM and, if you’re using one of the Marionette views, undo any bindings made by the view) and render a different view simply by calling show again, or you can just close the view by calling close. Regions can do more than that, but the fact that they handle the rendering and closing for you with a single function call makes them extremely useful. Here’s a code sample for those who speak in code rather than English:

// Create a region. It will control what's in the #container element.
var region = new Backbone.Marionette.Region({
  el: "#container"
});

// Add a view to the region. It will automatically render immediately.
region.show(new MyView());

// Close out the view that's currently there and render a different view.
region.show(new MyOtherView());

// Close out the view and display nothing in #container.
region.close();

If you want a Region directly on your application object (e.g. App.someRegion), there’s a simple way to add one quickly: addRegions. There are three ways to use addRegions. In every case, you would pass in an object whose property names will be added to the application as regions, but the value of each of these may be different depending on which way you wish to accomplish this.

Selector

Simply supply a selector, and a standard region will be created that uses that selector as its el property.

App.addRegions({
  container: "#container",
  footer:    "#footer"
});

// This is equivalent to
App.container = new Backbone.Marionette.Region({el:"#container"});
App.footer    = new Backbone.Marionette.Region({el:"#footer"});

Custom Region Type

You can extend Region to create your own types of regions. If you want to use your own type of region, you can use the syntax below. Note that, with this syntax, el must already be defined within your region type.

var ContainerRegion = Backbone.Marionette.Region.extend({
  el: "#container", // Must be defined for this syntax
  // Whatever other custom stuff you want
});

var FooterRegion = Backbone.Marionette.Region.extend({
  el: "#footer", // Must be defined for this syntax
  // Whatever other custom stuff you want
});

// Use these new Region types on App.
App.addRegions({
  container: ContainerRegion,
  footer:    FooterRegion
});

// This is equivalent to:
App.container = new ContainerRegion();
App.footer    = new FooterRegion();

Custom Region Type with Selector

If you don’t define el — or you want to override it — in your custom region type, then you can use this syntax:

var ContainerRegion = Backbone.Marionette.Region.extend({});

var FooterRegion = Backbone.Marionette.Region.extend({});

// Use these new Region types on App.
App.addRegions({
  container: {
    regionType: ContainerRegion,
    selector:   "#container"
  },
  footer: {
    regionType: FooterRegion,
    selector:   "#footer"
  }
});

// This is equivalent to:
App.container = new ContainerRegion({el:"#container"});
App.footer    = new FooterRegion({el:"#footer"});

As you can see, adding application-wide regions is dead simple (especially if you’re using the normal Region type), and they add a lot of useful functionality.

Conclusion

As you can already see, Marionette adds a ton of great features to make Backbone development simpler, and we’ve covered only one of many modules that it provides (plus, we’ve touched on a couple of other modules that Application itself uses, but there’s plenty more to learn about those). I hope this will entice Backbone programmers a bit and make you eager to read the rest of this series6, when I’ll cover more of the modules.

Credits of image on start page: Dmitry Baranovskiy7.

(al)

Footnotes

  1. 1 https://shop.smashingmagazine.com/better-backbone-applications-with-marionettejs.html
  2. 2 https://shop.smashingmagazine.com/smashing-library-complete.html
  3. 3 https://github.com/marionettejs/backbone.marionette
  4. 4 http://www.joezimjs.com/javascript/scalable-javascript-applications/
  5. 5 http://backbonejs.org/#Events
  6. 6 http://www.smashingmagazine.com/2013/04/02/thorough-introduction-backbone-marionette-part-2-modules/
  7. 7 http://www.flickr.com/photos/dmitry-baranovskiy/2378867408/

↑ Back to topShare on Twitter

Joseph Zimmerman is a web developer for Kaplan Professional and runs his own JavaScript blog. When he isn't feeding his coding obsession, he's spending time with his wife and two little boys.

Advertising
  1. 1

    Amazing improvement on an already awesome framework! Thanks for this.

    0
  2. 2

    Awesome intro, thank you!

    0
  3. 3

    Thanks for this. I would have liked some examples, such as when and why you would use regions. It’s hard for me to see a need for them.

    0
    • 4

      No worries. Regions are a somewhat large topic and I barely touched on them here. A future article will go into more depth on Regions.

      0
  4. 5

    In addition to my last comment. Article writer could you please not copy paste marionette’s github docs as it is in the article and provide original and more informative content.

    2
    • 6

      I understand the desire to have original code examples, but I didn’t feel it was necessary. The docs are very good and the examples contained in them are worth reusing.

      0
  5. 7

    Well good intro to marionette. However in my opinion the quality of article content dis not matched to the title of the article. if someone looking for advance hands on tutorial on marionette they should look at rob conery’s screencast which he recorded with derick bailey on tekpub.com. Last video in series where marionette comes in to the picture is free.

    0
    • 8

      That’s definitely a very good video. It’s a very nice introduction by way of walking through an application and showing how to change a normal Backbone app to use Marionette, but I’m not sure you realize that this is only part 1 of this series and only talks about the Application piece. There are some things covered here that weren’t in the video and I plan on covering nearly every piece of Marionette individually with long in-depth articles like this. Is there something missing that makes you consider this as not “thorough”?

      0
    • 9

      After watching that video for 15min, they had had plenty of jokey chat and barely mentioned Marionette.

      0
      • 10

        The video is nearly 1 hour 10 minutes long. Its nice to get the actual personality of the developers and not just humdrum robotic lecturing.

        0
        • 11

          On the other hand, it really annoys and wastes my time. It seems being really hard to find a good screencast author. I got a bit desperate until came across Andrew Burgess at tutsplus, who is quite close to Ryan Bates’ style. Kudos to him.

          2
  6. 12

    I think Marionette extension is something like an avoidable wrapper. Since I think in terms of a modular app, I use backbone.js with require.js to load modules. I can bootstrap my app in a main.js where I simply use a naming convention to dynamically load a context router or a whole view composition.
    From features described in this post, I would deserve to go deeper on event aggregators provided by Marionette … because I use to implements Backbone.listenTo and I never had to worry about exposing them globally.

    0
    • 13

      Don’t you worry. This is not all there is to Marionette. It’s kinda small, but above the main title of the article, it says “Part 1: Application”. I’ve only covered a very small portion of Marionette so far and probably more than a dozen articles should be coming out to explain the rest of it.

      0
  7. 14

    I’ve only used Backbone for a couple of apps, but usually I extend the View to create my main application object, and then instantiate and render the sub views in its render method, as opposed to extending the Router to serve as the main app (as noted in the article). Speaking outside of the context of Marionette, is this an anti-pattern, or just developer preference?

    0
    • 15

      Joseph Zimmerman

      March 19, 2013 3:30 am

      Using the Router has become the “norm”, but no one has really specified what the App should be. I think using the main View is actually a pretty interesting idea, but in all actuality, the main App shouldn’t be a View or a Router. It should be its own thing.

      0
  8. 16

    Very good intro! I’m pretty skilled at Backbone itself but kind of shuddered at the thought of adding another layer, especially when my apps weren’t really that complex to add it. But this was a really good introduction to Marionette. I’ve been seeing it popping up in job descriptions so sooner or later I’d have to pick it up. Definitely looking forward to the other parts of the series. Is there a timeline for when they come out? Just out of curiosity.

    0
  9. 17

    Thanks for the introduction Joseph! is helping me a lot in learning Marionette

    0
  10. 18

    Nice introduction on Marionette. Thanks for sharing!

    0
  11. 19

    Great, now where’s the rest of the series?

    0

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top