Modal service for AngularJS - supports creating popups and modals via a service. Full support for Angular 1.5+ components. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.
- Support for AngularJS 1.5.x Components
Install with Bower (or NPM):
bower install angular-modal-service# or...npm install angular-modal-service
Then reference the minified script:
Specify the modal service as a dependency of your application:
var app = angular;
Now just inject the modal service into any controller, service or directive where you need it.
showModal returns a promise which is resolved when the modal DOM element is created
and the controller for it is created. The promise returns a
modal object which contains the
element created, the controller, the scope and two promises:
closed. Both are
resolved to the result of the modal close function, but
close is resolved as soon as the
modal close function is called, while
closed is only resolved once the modal has finished
animating and has been completely removed from the DOM.
The modal controller can be any controller that you like, just remember that it is always
provided with one extra parameter - the
close function. Here's an example controller
for a bootstrap modal:
close function is automatically injected to the modal controller and takes the result
object (which is passed to the
closed promises used by the caller). It can
take an optional second parameter, the number of milliseconds to wait before destroying the
DOM element. This is so that you can have a delay before destroying the DOM element if you
are animating the closure. See Global Config for setting a default delay.
Now just make sure the
close function is called by your modal controller when the modal
should be closed and that's it. Quick hint - if you are using Bootstrap for your modals,
then make sure the modal template only contains one root level element, see the FAQ
for the gritty details of why.
To pass data into the modal controller, use the
inputs field of the modal options. For example:
year values into the controller:
You can also provide a controller function directly to the modal, with or without the
But if you provide
controller attribute with
as syntax and
controllerAs attribute together,
will have high priority.
Support for AngularJS 1.5.x Components
It's also possible to specify a component, rather than a template and controller. This can be done by providing a
component and an optional
bindings value to the
showModal function takes an object with these fields:
controller: The name of the controller to create. It could be a function.
controllerAs: The name of the variable on the scope instance of the controller is assigned to - (optional).
templateUrl: The URL of the HTML template to use for the modal.
templateUrlis not specified, you can specify
templateas raw HTML for the modal.
inputs: A set of values to pass as inputs to the controller. Each value provided is injected into the controller constructor.
component: Renders a modal with the provided component as its template
bindings: Optional. If
componentis provided, all properties in
bindingswill be bound to the rendered
appendElement: The custom angular element or selector (such as
#element-id) to append the modal to instead of default
scope: Optional. If provided, the modal controller will use a new scope as a child of
scope(created by calling
scope.$new()) rather than a new scope created as a child of
bodyClass: Optional. The custom css class to append to the body while the modal is open (optional, useful when not using Bootstrap).
preClose: Optional. A function which will be called before the process of closing a modal starts. The signature is
function preClose(modal, result, delay). It is provided the
resultwhich was passed to
delaywhich was passed to close.
locationChangeSuccess: Optional. Allows the closing of the modal when the location changes to be configured. If no value is set, the modal is closed immediately when the
$locationChangeSuccessevent fires. If
falseis set, event is not fired. If a number
nis set, then the event fires after
The Modal Object
modal object returned by
showModal has this structure:
modal.element- The created DOM element. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call
modalon this object to show the modal.
modal.scope- The new scope created for the modal DOM and controller.
modal.controller- The new controller created for the modal.
modal.close- A promise which is resolved when the modal
closefunction is called.
modal.closed- A promise which is resolved once the modal has finished animating out of the DOM.
The Modal Controller
The controller that is used for the modal always has one extra parameter injected, a function
close. Call this function with any parameter (the result). This result parameter is
then passed as the parameter of the
closed promises used by the caller.
Closing All Modals
Sometimes you may way to forcibly close all open modals, for example if you are going to transition routes. You can use the
ModalService.closeModals function for this:
optionalResult parameter is pased into all
close promises, the
optionalDelay parameter has the same effect as the controller
close function delay parameter.
ModalService cooperates with Angular's
$animate service to allow easy implementation of
custom animation. Specifically,
showModal will trigger the
ng-enter hook, and calling
close will trigger the
ng-leave hook. For example, if the
ngAnimate module is
installed, the following CSS rules will add fade in/fade out animations to a modal with the
ModalService exposes only one function,
showModal, error handling is always performed in the same way.
showModal function returns a promise - if any part of the process fails, the promise will be rejected, meaning
that a promise error handling function or
catch function can be used to get the error details:
Global Options Configuration
To configure the default options that will apply to all modals call
configureOptions on the
Here are the available global options:
closeDelay- This sets the default number of milliseconds to use in the close handler. This delay will also be used in the
closeModalsmethod and as the default for
To work with the code, just run:
npm install npm test npm start
The dependencies will install, the tests will be run (always a useful sanity check after a clean checkout) and the code will run. You can open the browser at localhost:8080 to see the samples. As you change the code in the
src/ folder, it will be re-built and the browser will be updated.
The easiest way to adapt the code is to play with some of the examples in the
Run tests with:
A coverage report is written to
Debug tests with:
npm run test-debug
This will run the tests in Chrome, allowing you to debug.
To create a release:
- Create the
npm run build
- Merge your work to master
npm run releaseto tag, bump the version numbers and update the changelog
- Push and deploy
git push --follow-tags && npm publish
Having problems? Check this FAQ first.
I'm using a Bootstrap Modal and the backdrop doesn't fade away
This can happen if your modal template contains more than one top level element. Imagine this case:
<!-- Some comment -->...some modal
When you create the modal, the Angular Modal Service will add both of these elements
to the page, then pass the elements to you as a jQuery selector. When you call bootstrap's
modal function on it, like this:
It will try and make both elements into a modal. This means both elements will get a backdrop.
In this case, either remove the extra elements, or find the specific element you need
from the provided
The backdrop STILL does not fade away after I call
close OR I don't want to use the 'data-dismiss' attribute on a button, how can I close a modal manually?
You can check the 'Complex' sample (complexcontroller.js). The 'Cancel' button closes without using the
data-dismiss attribute. In this case, just use the
preClose option to ensure the bootstrap modal is removed:
Another option is to grab the modal element in your controller, then call the bootstrap
to manually close the modal. Then call the
close function as normal:
I'm using a Bootstrap Modal and the dialog doesn't show up
Code is entered exactly as shown the example but when the showAModal() function fires the modal template html is appended to the body while the console outputs:
TypeError: undefined is not a function
Pointing to the code:
How can I prevent a Bootstrap modal from being closed?
If you are using a bootstrap modal and want to make sure that only the
close function will close the modal (not a click outside or escape), use the following attributes:
To do this programatically, use:
Problems with Nested Modals
If you are trying to nest Bootstrap modals, you will run into issues. From Bootstrap:
Bootstrap only supports one modal window at a time. Nested modals aren’t supported as we believe them to be poor user experiences.
Some people have been able to get them working (see https://github.com/dwmkerr/angular-modal-service/issues/176). Unfortunately, due to the lack of support in Bootstrap is has proven troublesome to support this in angular-modal-service.
Thanks go the the following contributors:
- DougKeller - Adding support for Angular 1.5 components.
- joshvillbrandt - Adding support for
- cointilt - Allowing the modal to be added to a custom element, not just the body.
- kernowjoe - controllerAs
- poporul - Improving the core logic around compilation and inputs.
- jonasnas - Fixing template cache logic.
- maxdow - Added support for controller inlining.
- kernowjoe - Robustness around locationChange
- arthur-xavier - Robustness when
- stormpooper - The new
- decherneyge - Provider features, global configuration,