Skip to content

Swapping page content with regions

derickbailey edited this page Jun 1, 2012 · 2 revisions

In a 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:

app mockup

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):
Region = (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

An in-depth use of the region 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);
  }
});

region.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.


originally posted at http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/