Building An Email List Component With BackboneJS

In my post about re-launching myself in to the independent life, I talked a little bit about restarting my effort to complete my Building Backbone Plugins eBook. I’ve already started down the path, reviewing existing chapters and beginning to fill in some of the missing pieces. My goal is to have the book content complete by the end of January, and have it edited well enough to call it done by the end of February. 

As part of my effort to get things done, I’m re-examining the flow of content and chapters. And I have to say coming back to this book after many months away is an eye opener in this regard. I immediately noticed several chapters out of place and an entire section of content that didn’t make sense in the flow of information. I’ve already taken steps to correct this and have reorganized several chapters and removed Part 5 of the book, absorbing the chapters into other parts. In the middle of all this, I also decided that one of the chapters from Part 5 does not need to be in the book at all – the chapter on building an email list component. Rather than toss the entire work in to the trash, though, I wanted to share this chapter with everyone. There’s a chance that it may find its way in to another book at another time, but that is yet to be determined.

What Is A Component?

There are a lot of different definitions of “component” floating around these days. For the purposes of this book, a generalized definition will be borrowed from the up-coming W3C standard for Web Components, and from frameworks such as AngularJS which provide a way to build component based applications.

Components are a combination of visual portions of the application and the logic and processing of that visualization. They encapsulate a small feature or sub-set of a feature in a manner that allows the component to be wired together with other components, creating a larger feature set or functional area of an application. They have at least one view with some amount of logic and process (a.k.a. “workflow”).

Web Components:

For more information on Web Components, see this work-in-progress document from the W3C and the Polymer project. AngularJS is also a current framework that builds on the ideas of component based architecture and can be found at AngularJS.org.

Email Apps And Components

A typical email app has several distinct areas of the application’s screen. There is a list of categories or labels, a list of email to show for a given mail box, a search or filter box, and an individual email view, for example. Each of these – and likely additional areas of functionality on the screen – can be composed in to small workflow objects as components of the larger email work flow.

The classic example of Gmail illustrates all of these basic components, and many more.

Gmail components

The primary email screen shows a list of categories or labels to the left, a list of email to the right, a search screen at the top, filters, chat sessions, and much more. Each of these areas of functionality can be broken down in to separate components that can then be orchestrated to created a more functional system. This orchestration happens through an API that each of the components exposes, with a higher level workflow (as discussed in the previous chapter) controlling all of the individual components.

Building An Email List Component

In GMail, the email list that shows the list of mail for the currently selected label or category, applying any filters or search criteria, etc. It may sound like it has a lot of responsibilities, but this can be very easily mitigated with good application design.

Assume the email list is built as a component within the larger screen. There are other components on the screen, as well. Many of them will deal with the raw list of email in some way (not the display of the list, but the actual email data list). One will display the list, one will filter the list, one will search within the list, and possibly more. If multiple component are dealing with the data in some way, it does not make sense for any one of them to have sole responsibility for managing that list. Each component, then, will only have responsibility for it’s use of the list and for exposing an API that lets other parts of the app know what manipulation is occurring.

Before getting to the coordination of components, though, take this idea in to account and build a component to display the list of email.

[Note: A Base Component]

In the book, there is an entire chapter dedicated to building the base component, explaining why you want each of the things in place. For this post, though, I’m not going to re-build the entire base component. Instead, I’m going to create an alias to an existing object inside of MarionetteJSthe Controller object. This object contains the same core capabilities and structure as the Component base in the book. In fact, the Controller in Marionette is what I have been using to build my Components in real projects and is what inspired these chapters in the first place.

For the sake of this blog post, then, a Component base will be defined with this simple variable assignment:

var Component = Marionette.Controller;

Defining The Component, Top Down

Start by extending from the Component type, and add an initialize method that looks for a mailList attribute on the options. Assume this is a Backbone.Collection instance, representing the email that should be displayed.

var MailListComponent = Component.extend({

  initialize: function(options){
    this.mailList = options.mailList;
  }

});

Next, you’ll need a view to display the list of email. Since the data is in a Backbone.Collection, you can use the CollectionView and ItemView from the first part of this book to do that. Just define a template for the items, and create view definitions appropriately.

<script type="text/html" id="email-list-item-template">
  <span class="from"><%= from %></span>
  <span class="subject"><%= subject %></span>
  <span class="date"><%= date %></span>
</script>


var MailItemView = ItemView.extend({
  tagName: "li",
  className: "email",
  template: "#email-list-item-template"
});

var MailListView = CollectionView.extend({
  tagname: "ul",
  itemView: MailitemView
});

Now within the Component, add a show method that takes the views, renders them, and shows them in the region that the Component is referencing.

var MailListComponent = Component.extend({
  initialize: function(options){
    this.mailList = options.mailList;
  },

  show: function(){
    var mailView = new MailListView({
      collection: this.mailList
    });

    this.region.show(mailView);
  }
});

And there you have it – a very basic component with which to show the list of email. Although, this is a rather simple example, it illustrates the basics of creating a component.

Exposing An API For Mail Item Selection

To make the MailListComponent more useful, it would be good for it to expose an API that allows other objects to know when a mail item has been selected. The easiest way to do this with a backbone application is with events, and the MailListComponent can trigger an event stating a mail item was selected.

For it to expose this method appropriately, though, it will need to know when a mail item is selected or clicked in the case of using a mouse. Listening to an event from the collection to know when a single item is selected would be ideal. But you don’t necessarily have control over the collection definition for the email. Wouldn’t it be nice if you could wrap the collection with the additional functionality of selecting an item? And doesn’t that just sound so familiar?

Take the MultiPickCollection from Chapter 9, and set it up inside of the component.

var MailListComponent = Component.extend({
  initialize: function(options){
    // build the MultiPickCollection
    this.mailList = options.mailList;
    this.pickable = new Backbone.Picky.MultiPickCollection(this.mailList);
  },

  // â

The MailListView can assume it is using a pickable collection with pickable model instances in the item view, as well.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Backbone, Books, E-Books, HTML5, Javascript, Marionette, Model-View-Controller, Model-View-Presenter, Modules. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Matt

    Why do not you do that using modules?

    • http://mutedsolutions.com Derick Bailey

      modules are a completely separate concern. if you’re a fan of modules, then use modules for the deployment and inclusion in other parts of your app. that doesn’t have anything to do with the design of the code inside of the module, though. it’s a bit like asking “why not deliver that computer via UPS?” when i’m writing an article about how to design motherboards :)

  • Luiz Americo Pereira Camara

    Should not be this.pickable instead of this.collection in

    this.listenTo(this.collection, “picked”, this.emailSelected); ?

  • Mark LeMerise

    Great article as usual, Derick. Quick question: what are the core capabilities that you require for a component, thus basing it off Marionette.Controller? Or do I have to buy the book? :P

    • http://mutedsolutions.com Derick Bailey

      its more a pattern of use than set of capabilities, i think. in my case, i use Marionette.Controller because it provides the .extend method that backbone apps already know, gives a “initialize” method on the object, and have the Backbone.Events mixed in to it already. This makes it easy for me to add a little bit more code, like the use of a region, and have a basic “component” in place. But again, it’s more a pattern of use than anything else. Creating an encapsulated thing – something that includes a small UI along with the logic to process that UI – that can be composed in to a larger page or feature… that’s really what a component is all about.