UI Bootstrap $modal: get list of all opened modals

Ui-bootstrap is a wonderful Swiss-army knife for any javascript developer that wants to get things looking sleek and get going fast. Name whatever you need: calendars, fancy buttons, collapsible content, tooltips, modals (popups); this collection of libraries delivers.

$modal is a widely used service to create dialogs/popups and its usage is very straightforward, However, the simplicity of usage comes at a price. Don’t worry, using $modal doesn’t entail hunting for obscure ingredients, using an obscene amount of scented candles and drawing pentagrams. You will notice though that as soon as you want to use the library in a way which deviates from the way it was intended to be used, you’re going end up like a teenager getting home drunk from his first party and being caught by his parents in the less than reputable state of inebriation; in trouble.

Vanilla $modal

One of the thing one can expect of a library that in its essence creates popups and allows you to close them is to have the possibility to close all those popups at the same time. You are in luck there, because the library does provide you with that option, but if you want to close the popups based on a certain property or close all popups of a certain type, you are out of luck; you have an access only to the popups you keep a reference to, or to the function that closes them globally.

Keeping a list of opened modals

While that seems sufficient, sometimes your application might need to make decisions on opening or closing modals at a place in your business logic and application flow that doesn’t have access to all other opened modals and their configuration.

Close em’ all, the sole and very much insufficient option

So what you are left with in vanilla $modal is the option to be like a Pokemon master and ‘close em’ all’, but that just restricts you if you want to close a specific modal and keep the others opened. There is an issue and a pull request I opened with the guys on ui-bootstrap for all the people who would want to have a bit more control than the ‘kill all’ approach that vanilla $modal provides you with.

The informed approach, keeping a list of opened modals

To make an informed decision to see which modals are opened, what type they are and what their config is, you can’t use vanilla $modal and you have two options: either register every modal you open with a service of yours and de-register it on closing with the same service, or extend $modal so that it keeps a list of opened modals and their config. Following the single responsibility principle it’d be logical to actually extend $modal. Here is a Plunkr that does that: decorating $modal to keep a list of opened modals.

The code

The relevant code is this one (needs inclustion of lodash for looping own props but you can implement it in pure js):

.config(['$provide', function($provide){
$provide.decorator('$modal', function($delegate){
var original = $delegate.open;
var wrapFunction = function wrapFunction (obj, functionName, callback){
var originalFunction = obj[functionName];
obj[functionName] = function(){
var result = originalFunction.apply(this, arguments);
callback.apply(this, arguments);
return result;
};
};
var getRandom = function getRandom(){
return Math.floor((Math.random() * 10000000000));
};
var openedModals = {};
$delegate.open = function open (config){
var modal = original.apply(this, arguments);
var idx = getRandom();
openedModals[idx] = {
modal: modal,
config: config
};
modal.result['finally'](function(){
delete openedModals[idx];
});
wrapFunction(modal, 'close', function(){
delete openedModals[idx];
});
wrapFunction(modal, 'dismiss', function(){
delete openedModals[idx];
});
return modal;
};
$delegate.getOpenedModals = function(){
var mods = [];
_.forOwn(openedModals, function(modal){
mods.push(modal);
});
return mods;
}
return $delegate;
});
}])
view raw decorating $modal hosted with ❤ by GitHub

Basically what you do is you wrap around the open/close methods of $modal and keep a list of opened modals which is exposed in the $modal’s getOpenedModals. Then in your controllers/services you can just inject $modal and apart from having only the open method, it is going to also have the getOpenedModals which is going to retrieve you a list of all opened modals so you can close/dismiss them selectively or make decision on opening a new modal based on the existence of another in the list of opened ones.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.