Using Marionette to Display Modal Views

For a while, I’ve been thinking about how best to handle showing modal dialog boxes for my applications while utilizing Backbone views. A lot of interesting ideas passed through my head, but none of them seemed exactly right. Then I saw a post by Derick Bailey where he described how he uses Marionette’s Regions to handle the work. His post is a bit on the old side and Regions have changed a bit since, so I decided to look into how to do it myself.

The Issues

There are several issues surrounding creating modal dialogs just with a view. As Derick talks about in his article, most plugins for creating these dialogs will remove (or just move) the actual element from DOM, so any events that you set up in the view will be lost.

Along with that, we lose reusability. By making the view handle the work of controlling the modal, it can’t be used in a place where you don’t want a modal window. By moving the modal functionality out of the view, it can be used anywhere in the application.

The Solution

Now that we know we need to pull the modal functionality out of the views, it’s just a matter or figuring out where to put it. Marionette’s Regions are perfect for this. Regions are objects that represent a place that already exists in the DOM and they handle adding and removing views to/from that place in the DOM. Simply call show on a Region to add a view there and call close to remove it.

All we need to do is augment a Region to call the plugin’s method for showing the modal when the view is shown, make sure to hide the modal when the view is closed, and close the view when the modal is hidden.

Here I’ve developed a ModalRegion that uses Twitter Bootstrap’s modal plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var ModalRegion = Marionette.Region.extend({
constructor: function() {
Marionette.Region.prototype.constructor.apply(this, arguments);

this.ensureEl();
this.$el.on('hidden', {region:this}, function(event) {
event.data.region.close();
});
},

onShow: function() {
this.$el.modal('show');
},

onClose: function() {
this.$el.modal('hide');
}
});

There are a few things worth noting here:

  • I created a constructor function instead of initialize. This is because if someone extends this Region, they’ll override the initialize function with theirs. This way, it won’t be overridden.
  • I call this.ensureEl(). This is a Region’s method for caching the jQuery object for the Regions element to this.$el. Normally, this method is called in its show method, but we needed this.$el to be set up before that.
  • There’s some strange things happening in that event handler:
    • The ‘hidden’ event is fired by Twitter Bootstrap after it hides the modal.
    • The object that is passed in as the second parameter to on is a data object that is attached to event as its data property. This isn’t commonly used, so many people don’t know it exists. If this is new to you, check out the API. I passed in this object as a way to make sure that the close method was called on the region with the right context. There are several alternative ways to do this, and this probably isn’t the best way, but it avoids a closure and it helps me to teach you something you not have known about before.
    • onShow and onClose are called immediately after the show and close methods are finished. This is a simple way for us to augment the show and close methods to do more than they normally do without overriding the functions.

Now it’s simple to use:

1
2
3
4
var modal = new ModalRegion({el:'#modal'});
var view = new SomeView();

modal.show(view);

Conclusion

As simple as that. This can be changed pretty easily to use other plugins such as jQueryUI, KendoUI, Wijmo, etc. Also, now that the modal functionality is in one place, if you end up switching the plugin that you use, you only have to change the code in this region and everything should work fine. The only thing you’ll need to work at is getting all the modal-specific markup in there. God bless and happy coding.

Author: Joe Zimmerman

Author: Joe Zimmerman Joe Zimmerman has been doing web development ever since he found an HTML book on his dad's shelf when he was 12. Since then, JavaScript has grown in popularity and he has become passionate about it. He also loves to teach others though his blog and other popular blogs. When he's not writing code, he's spending time with his wife and children and leading them in God's Word.