Composite JS Apps: Regions And Region Managers

In my previous post on Composite JavaScript Apps, I introduced a few of the high level design ideas and implementation details that I have been using in an application that I’m building. Since then, the requirements for that app have grown significantly and I’ve made more progress toward a better composite application design.

Content Swapping

My simple item management application started out with nothing more than these three regions on the screen:

NewImage

Once this was in place, though, a new requirement came along… a complex search with search results. To implement this, I needed to modify the application’s interface to swap the grid and add/edit form out and put in a search results screen instead. The idea is that when the user does a search, the main content area will show the search results. The user can then go back to the location management aspect of the app whenever they need to. After a bit of searching, I found a high level pattern that made this easy, and also realized that I had previously implemented the core of this pattern without knowing it.

Microsoft Prism: Regions and Region Managers

Several years ago, Microsoft released a framework for it’s WPF and Silverlight runtimes, called Prism. This was essentially the big composite app framework that people used to build well structured and decoupled apps in XAML. I never had a chance to use this framework directly, but I worked with a team of developers that did use it.

One of the things that I liked about what I saw in Prism was the way it used the idea of “regions” and “region managers” to compose the user interface. The gist of it is that you could define a visible area of the screen and build out the most basic layout for it without knowing what content was going to be displayed in it at runtime. Then at runtime, your application modules could register themselves to have content displayed in the various regions of the screen.

This pattern fits perfectly with the direction that my Backbone app is heading, so I decided to borrow the names and build my own version in JavaScript.

A Simple Region Manager

In Prism, a region is defined in the XAML markup. In web applications, it’s defined in HTML markup. Similarly, in XAML a region manager is code that you write in C# or other .NET languages, while a region manager in a web app is going to be JavaScript. Backbone.js provides a good separation between the markup and the code to run that markup through it’s Views, so I initially thought about going down this path for my region manager. After a bit of thinking, though, I realized that I didn’t necessarily need a Backbone view. What I really need, at the very core, is a JavaScript object that do the following:

  • Represent an existing DOM node
  • Change out the contents of that DOM node
  • Call any required rendering and initialization for content views that will be displayed
  • Call any required cleanup for content views when they are removed

What I came up with as an initial pass at handling these needs, is the following (hard coded specifically to use a “#mainregion” element from the DOM):

RegionManager = (function (Backbone, $) {
    var currentView;
    var el = "#mainregion";
    var region = {};

    var closeView = function (view) {
        if (view && view.close) {
            view.close();
        }
    };

    var openView = function (view) {
        view.render();
        $(el).html(view.el);
        if (view.onShow) {
            view.onShow();
        }
    };

    region.show = function (view) {
        closeView(currentView);
        currentView = view;
        openView(currentView);
    };

    return region;
})(Backbone, jQuery);

Does that look familiar? It certainly does to me. I’ve written this same code dozens of times and blogged about it in my Zombies! RUN! post. So, it turns out that I’ve been using what I’m now calling a “region manager” for a while – I just didn’t realize it, previously. Oh, happy day! I’m just formalizing a concept I had introduced somewhere else, instead of having to create something new and unknown. :)

Using The Region Manager

An in-depth use of the region manager has been covered in my Zombies post already. As a refresher, though, you only need to provide a Backbone view to the `show` method and the region manager will take over from there.

MyView = Backbone.View.extend({
  render: function(){
    $(this.el).html("some html contents");
    $(this.el).hide();
  },

  close: function(){
    this.remove();
    this.unbind();
  },

  onShow: function(){
    $(this.el).show(500);
  }
});

RegionManager.show(new MyView());

The usual `close` method exists so we can handle our zombie problems. I’ve also added a bit more to the API that the region manager can handle, making it more robust and allowing it to handle more complex UI needs. Specifically, an `onShow` method fires on your view if you’ve provided one, just after the view’s `el` has been added to the DOM. This method will let you call into code that expects the DOM elements to exist, to manipulate them.

In this simple example, I’m using the `onShow` to fade the contents of the view in to view, using jQuery’s `.show` method and giving it a 500 milliseconds (1/2 of 1 second) time to do the fade. It’s a simple idea, but one that I’ve found is needed when using some libraries, such as the jQuery layout plugin. Again, this isn’t an idea that I came up with, either. I took this directly from my experience in working with WinForms applications. `onShow` is a standard event in the lifecycle of a Windows form, in .NET. It works well there, and it works well here in JavaScript, too.

But Wait! There’s More!

Well, maybe there isn’t anything more at this point in time. But there will be soon. As I’m traveling down the composite application path, I’m starting to extract the useful bits into a library so that I don’t have to rebuild the same things over and over again. If you’re interested in watching this grow over time, checkout my Backbone.Marionette repository on Github. It’s nearly empty at the time of writing this blog post, as it’s a work in progress. I plan on making a large announcement about it when I have more to share, sometime in the future.


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

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, Composite Apps, Javascript, Marionette. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://twitter.com/ojohnnyo Johnny Oshika

    Another great post, Derick.

  • Rinat Silnov

    Great approach, Derick. How do you use it with different regions (without hard coded “#mainregion”) ? If you need for example change one region without removing another?

    • http://mutedsolutions.com Derick Bailey

      I’ve turned this basic code in to a constructor function instead of a module, in my Backbone.Marionette framework so that I can create instances of Region objects and assign an `el` to each region instance. 

      It’s pretty simple code, for the most part. http://derickbailey.github.com/backbone.marionette/docs/backbone.marionette.html#section-34