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 | var ModalRegion = Marionette.Region.extend({ |
There are a few things worth noting here:
- I created a
constructor
function instead ofinitialize
. This is because if someone extends this Region, they’ll override theinitialize
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 tothis.$el
. Normally, this method is called in itsshow
method, but we neededthis.$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 toevent
as itsdata
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 theclose
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
andonClose
are called immediately after theshow
andclose
methods are finished. This is a simple way for us to augment theshow
andclose
methods to do more than they normally do without overriding the functions.
Now it’s simple to use:
1 | var modal = new ModalRegion({el:'#modal'}); |
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.