1 <!-- ### LOOKING FOR MAINTAINER. PLEASE PING [@voronianski](https://twitter.com/voronianski)! -->
4 [![build status](http://img.shields.io/travis/likeastore/ngDialog.svg)](https://travis-ci.org/likeastore/ngDialog)
5 [![npm version](http://badge.fury.io/js/ng-dialog.svg)](http://badge.fury.io/js/ng-dialog)
6 [![github tag](https://img.shields.io/github/tag/likeastore/ngDialog.svg)](https://github.com/likeastore/ngDialog/tags)
7 [![Download Count](https://img.shields.io/npm/dm/ng-dialog.svg)](http://www.npmjs.com/package/ng-dialog)
8 [![Code Climate](https://codeclimate.com/github/likeastore/ngDialog/badges/gpa.svg)](https://codeclimate.com/github/likeastore/ngDialog)
10 > Modal dialogs and popups provider for [AngularJS](http://angularjs.org/) applications.
12 ngDialog is ~10KB (minified), has minimalistic API, is highly customizable through themes and has only AngularJS as dependency.
14 ### [Demo](http://likeastore.github.io/ngDialog)
18 You can download all necessary ngDialog files manually, or install it with bower:
21 bower install ng-dialog
32 You need only to include ``ngDialog.js``, ``ngDialog.css`` and ``ngDialog-theme-default.css`` (as minimal setup) to your project and then you can start using the ``ngDialog`` provider in your directives, controllers and services. For example:
34 <link rel="stylesheet" href="lib/ng-dialog/css/ngDialog.min.css">
35 <link rel="stylesheet" href="lib/ng-dialog/css/ngDialog-theme-default.min.css">
36 <script src="lib/ng-dialog/js/ngDialog.min.js"></script>
38 Define the className to be the ``ngDialog-theme-default``.
40 For example in controllers:
43 var app = angular.module('exampleApp', ['ngDialog']);
45 app.controller('MainCtrl', function ($scope, ngDialog) {
46 $scope.clickToOpen = function () {
47 ngDialog.open({ template: 'popupTmpl.html', className: 'ngdialog-theme-default' });
54 Your help is appreciated! If you've found a bug or if something is not clear, please raise an issue.
56 Ideally, if you've found an issue, you will submit a PR that meets our [contributor guidelines][contributor-guidelines].
61 git clone git@github.com:likeastore/ngDialog.git
69 ngDialog service provides easy to use and minimalistic API, but in the same time it's powerful enough. Here is the list of accessible methods that you can use:
73 ### ``.open(options)``
75 Method allows to open dialog window, creates new dialog instance on each call. It accepts ``options`` object as the only argument.
79 ##### ``template {String}``
81 Dialog template can be loaded through ``path`` to external html template or ``<script>`` tag with ``text/ng-template``:
84 <script type="text/ng-template" id="templateId">
85 <h1>Template heading</h1>
86 <p>Content goes here</p>
91 ngDialog.open({ template: 'templateId' });
94 Also it is possible to use a simple string as template together with ``plain`` option.
96 ##### Pro Tip about templates
98 It's not always necessary to place your external html template inside ``<script>`` tag. You could put these templates into ``$templateCache`` like this:
101 angular.module('dialog.templates').run(['$templateCache', function($templateCache) {
102 $templateCache.put('templateId', 'template content');
106 Then it would be possible to include the ``dialog.templates`` module into the dependencies of your main module and start using this template as ``templateId``.
108 There is no need to do these actions manually.
109 You could use one of the plugins specifically for these purposes. They are available for different build systems including most popular Gulp / Grunt:
111 - [gulp-angular-templatecache](https://github.com/miickel/gulp-angular-templatecache)
112 - [gulp-ng-html2js](https://www.npmjs.com/package/gulp-ng-html2js)
113 - [grunt-html2js](https://github.com/karlgoldstein/grunt-html2js)
114 - [broccoli-html2js](https://www.npmjs.com/package/broccoli-html2js)
116 You could find more detailed examples on each of these pages.
118 ##### ``plain {Boolean}``
120 If ``true`` allows to use plain string as template, default ``false``:
124 template: '<p>my template</p>',
129 ##### ``controller {String} | {Array} | {Object}``
131 Controller that will be used for the dialog window if necessary. The controller can be specified either by referring it by name or directly inline.
135 template: 'externalTemplate.html',
136 controller: 'SomeController'
144 template: 'externalTemplate.html',
145 controller: ['$scope', 'otherService', function($scope, otherService) {
151 ##### ``controllerAs {String} ``
153 You could optionally specify `controllerAs` parameter for your controller. Then inside your template it will be possible to refer this controller by the value specified by `controllerAs`.
155 Usage of `controllerAs` syntax is currently recommended by the AngularJS team.
157 ##### ``resolve {Object.<String, Function>}``
159 An optional map of dependencies which should be injected into the controller.
160 If any of these dependencies are promises, ngDialog will wait for them all to be resolved
161 or one to be rejected before the controller is instantiated.
163 If all the promises are resolved successfully, the values of the resolved promises are
168 - `key` – `{String}`: a name of a dependency to be injected into the controller.
169 - `factory` - `{String | Function}`: If `String` then it is an alias for a service.
170 Otherwise if `Function`, then it is injected using `$injector.invoke` and the return
171 value is treated as the dependency. If the result is a promise, it is resolved
172 before its value is injected into the controller.
177 controller: function Ctrl(dep) {/*...*/},
179 dep: function depFactory() {
186 ##### ``scope {Object}``
188 Scope object that will be passed to the dialog. If you use a controller with separate ``$scope`` service this object will be passed to the ``$scope.$parent`` param:
194 template: 'externalTemplate.html',
195 className: 'ngdialog-theme-plain',
201 <script type="text/ng-template" id="externalTemplate.html">
202 <p>External scope: <code>{{value}}</code></p>
206 ##### ``scope.closeThisDialog(value)``
208 In addition ``.closeThisDialog(value)`` method gets injected to passed ``$scope``. This allows you to close the dialog straight from the handler in a popup element, for example:
211 <div class="dialog-contents">
213 <input type="button" value="OK" ng-click="checkInput() && closeThisDialog('Some value')"/>
217 Any value passed to this function will be attached to the object which resolves on the close promise for this dialog. For dialogs opened with the ``openConfirm()`` method the value is used as the reject reason.
219 ##### ``data {String | Object | Array}``
221 Any serializable data that you want to be stored in the controller's dialog scope. (``$scope.ngDialogData``). From version `0.3.6` `$scope.ngDialogData` keeps references to the objects instead of copying them.
223 Additionally, you will have the dialog id available as ``$scope.ngDialogId``. If you are using ``$scope.ngDialogData``, it'll be also available under ``$scope.ngDialogData.ngDialogId``.
225 ##### ``className {String}``
227 This option allows you to control the dialog's look, you can use built-in [themes](https://github.com/likeastore/ngDialog#themes) or create your own styled modals.
229 This example enables one of the built-in ngDialog themes - ``ngdialog-theme-default`` (do not forget to include necessary css files):
233 template: 'templateId',
234 className: 'ngdialog-theme-default'
237 Note: If the className is not mentioned, the dialog will not display correctly.
239 Check [themes](https://github.com/likeastore/ngDialog#themes) block to learn more.
241 ##### ``appendClassName {String}``
243 Unlike the `className` property, which overrides any default classes specified through the `setDefaults()` method ([see docs](https://github.com/likeastore/ngDialog#setdefaultsoptions)), `appendClassName` allows for the addition of a class on top of any defaults.
245 For example, the following would add both the `ngdialog-theme-default` and `ngdialog-custom` classes to the dialog opened:
248 ngDialogProvider.setDefaults({
249 className: 'ngdialog-theme-default'
254 template: 'template.html',
255 appendClassName: 'ngdialog-custom'
259 ##### ``disableAnimation {Boolean}``
261 If ``true`` then animation for the dialog will be disabled, default ``false``.
263 ##### ``overlay {Boolean}``
265 If ``false`` it allows to hide the overlay div behind the modals, default ``true``.
267 ##### ``showClose {Boolean}``
269 If ``false`` it allows to hide the close button on modals, default ``true``.
271 ##### ``closeByEscape {Boolean}``
273 It allows to close modals by clicking the ``Esc`` key, default ``true``.
275 This will close all open modals if there are several of them opened at the same time.
277 ##### ``closeByNavigation {Boolean}``
279 It allows to close modals on state change (history.back, $state.go, etc.), default ``false``.
280 Compatible with ui-router and angular-router.
281 Set this value to true if you want your modal to close when you go back or change state.
282 Set this value to false if you want your modal to stay open when you change state within your app.
284 This will close all open modals if there are several of them opened at the same time.
286 ##### ``closeByDocument {Boolean}``
288 It allows to close modals by clicking on overlay background, default ``true``. If [Hammer.js](https://github.com/EightMedia/hammer.js) is loaded, it will listen for ``tap`` instead of ``click``.
290 ##### ``appendTo {String}``
292 Specify your element where to append dialog instance, accepts selector string (e.g. ``#yourId``, ``.yourClass``). If not specified appends dialog to ``body`` as default behavior.
294 ##### ``cache {Boolean}``
296 Pass ``false`` to disable template caching. Useful for developing purposes, default is ``true``.
298 ##### ``name {String} | {Number}``
300 Give a name for a dialog instance. It is useful for identifying specific dialog if there are multiple dialog boxes opened.
302 ##### ``preCloseCallback {String} | {Function}``
304 Provide either the name of a function or a function to be called before the dialog is closed. If the callback function specified in the option returns ``false`` then the dialog will not be closed. Alternatively, if the callback function returns a promise that gets resolved the dialog will be closed.
306 The ``preCloseCallback`` function receives as a parameter ``value`` which is the same value sent to ``.close(id, value)``.
308 The primary use case for this feature is a dialog which contains user actions (e.g. editing data) for which you want the ability to confirm whether to discard unsaved changes upon exiting the dialog (e.g. via the escape key).
310 This example uses an inline function with a ``window.confirm`` call in the ``preCloseCallback`` function:
314 preCloseCallback: function(value) {
315 if (confirm('Are you sure you want to close without saving your changes?')) {
323 In another example, a callback function with a nested confirm ngDialog is used:
327 preCloseCallback: function(value) {
328 var nestedConfirmDialog = ngDialog.openConfirm({
330 <p>Are you sure you want to close the parent dialog?</p>\
331 <div class="ngdialog-buttons">\
332 <button type="button" class="ngdialog-button ngdialog-button-secondary" ng-click="closeThisDialog(0)">No</button>\
333 <button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="confirm(1)">Yes</button>\
338 // NOTE: return the promise from openConfirm
339 return nestedConfirmDialog;
344 ##### ``trapFocus {Boolean}``
346 When ``true``, ensures that the focused element remains within the dialog to conform to accessibility recommendations. Default value is ``true``
348 ##### ``preserveFocus {Boolean}``
350 When ``true``, closing the dialog restores focus to the element that launched it. Designed to improve keyboard accessibility. Default value is ``true``
352 ##### ``ariaAuto {Boolean}``
354 When ``true``, automatically selects appropriate values for any unspecified accessibility attributes. Default value is ``true``
356 See [Accessibility](#Accessibility) for more information.
358 ##### ``ariaRole {String}``
360 Specifies the value for the ``role`` attribute that should be applied to the dialog element. Default value is ``null`` (unspecified)
362 See [Accessibility](#Accessibility) for more information.
364 ##### ``ariaLabelledById {String}``
366 Specifies the value for the ``aria-labelledby`` attribute that should be applied to the dialog element. Default value is ``null`` (unspecified)
368 If specified, the value is not validated against the DOM. See [Accessibility](#Accessibility) for more information.
370 ##### ``ariaLabelledBySelector {String}``
372 Specifies the CSS selector for the element to be referenced by the ``aria-labelledby`` attribute on the dialog element. Default value is ``null`` (unspecified)
374 If specified, the first matching element is used. See [Accessibility](#Accessibility) for more information.
376 ##### ``ariaDescribedById {String}``
378 Specifies the value for the ``aria-describedby`` attribute that should be applied to the dialog element. Default value is ``null`` (unspecified)
380 If specified, the value is not validated against the DOM. See [Accessibility](#Accessibility) for more information.
382 ##### ``ariaDescribedBySelector {String}``
384 Specifies the CSS selector for the element to be referenced by the ``aria-describedby`` attribute on the dialog element. Default value is ``null`` (unspecified)
386 If specified, the first matching element is used. See [Accessibility](#Accessibility) for more information.
388 ##### ``width {Number | String}``
390 This option allows you to control the dialog's width. Default value is `null` (unspecified)
392 If you provide a Number, 'px' will be appended. To use a custom metric, use a String, e.g. `'40%'`.
394 For example, the following will add `width: 400px;` to the dialog when opened:
398 template: 'template.html',
403 In another example, the following will add `width: 40%;`:
407 template: 'template.html',
412 ##### ``height {Number | String}``
414 This option allows you to control the dialog's height. Default value is `null` (unspecified)
416 If you provide a Number, 'px' will be appended. To use a custom metric, use a String, e.g. `'40%'`.
418 For example, the following will add `height: 400px;` to the dialog when opened:
422 template: 'template.html',
427 In another example, the following will add `height: 40%;`:
431 template: 'template.html',
438 The ``open()`` method returns an object with some useful properties.
440 ##### ``id {String}``
442 This is the ID of the dialog which was just created. It is the ID on the dialog's DOM element.
444 ##### ``close(value) {Function}``
446 This is a function which will close the dialog which was opened by the current call to ``open()``. It takes an optional value to pass to the close promise.
448 ##### ``closePromise {Promise}``
450 A promise which will resolve when the dialog is closed. It is resolved with an object containing: ``id`` - the ID of the closed dialog, ``value`` - the value the dialog was closed with, ``$dialog`` - the dialog element which at this point has been removed from the DOM and ``remainingDialogs`` - the number of dialogs still open.
452 The value property will be a special string if the dialog is dismissed by one of the built in mechanisms: `'$escape'`, `'$closeButton'` or `'$document'`.
454 This allows you do to something like this:
457 var dialog = ngDialog.open({
458 template: 'templateId'
461 dialog.closePromise.then(function (data) {
462 console.log(data.id + ' has been dismissed.');
468 ### ``.setDefaults(options)``
470 You're able to set default settings through ``ngDialogProvider``:
473 var app = angular.module('myApp', ['ngDialog']);
474 app.config(['ngDialogProvider', function (ngDialogProvider) {
475 ngDialogProvider.setDefaults({
476 className: 'ngdialog-theme-default',
479 closeByDocument: true,
487 ### ``.openConfirm(options)``
489 Opens a dialog that by default does not close when hitting escape or clicking outside the dialog window. The function returns a promise that is either resolved or rejected depending on the way the dialog was closed.
493 The options are the same as the regular [``.open()``](https://github.com/likeastore/ngDialog#options) method with an extra function added to the scope:
495 ##### ``scope.confirm()``
497 In addition to the ``.closeThisDialog()`` method. The method ``.confirm()`` is also injected to passed ``$scope``. Use this method to close the dialog and ``resolve`` the promise that was returned when opening the modal.
499 The function accepts a single optional parameter which is used as the value of the resolved promise.
502 <div class="dialog-contents">
504 <button ng-click="closeThisDialog()">Cancel</button>
505 <button ng-click="confirm()">Confirm</button>
511 An Angular promise object that is resolved if the ``.confirm()`` function is used to close the dialog, otherwise the promise is rejected. The resolve value and the reject reason is defined by the value passed to the ``confirm()`` or ``closeThisDialog()`` call respectively.
517 Method accepts dialog's ``id`` and returns a ``Boolean`` value indicating whether the specified dialog is open.
521 ### ``.close(id, value)``
523 Method accepts dialog's ``id`` as string argument to close specific dialog window, if ``id`` is not specified it will close all currently active modals (same behavior as ``.closeAll()``). Takes an optional value to resolve the dialog promise with (or all dialog promises).
527 ### ``.closeAll(value)``
529 Method manages closing all active modals on the page. Takes an optional value to resolve all of the dialog promises with.
533 ### ``.getOpenDialogs()``
535 Method that returns array which includes the ids of opened dialogs.
539 ### ``.setForceHtmlReload({Boolean})``
541 Adds an additional listener on every ``$locationChangeSuccess`` event and gets update version of ``html`` into dialog. May be useful in some rare cases when you're dependant on DOM changes, defaults to ``false``. Use it in module's config as provider instance:
544 var app = angular.module('exampleApp', ['ngDialog']);
546 app.config(function (ngDialogProvider) {
547 ngDialogProvider.setForceHtmlReload(true);
553 ### ``.setForceBodyReload({Boolean})``
555 Adds additional listener on every ``$locationChangeSuccess`` event and gets updated version of ``body`` into dialog. Maybe useful in some rare cases when you're dependant on DOM changes, defaults to ``false``. Use it in module's config as provider instance:
558 var app = angular.module('exampleApp', ['ngDialog']);
560 app.config(function (ngDialogProvider) {
561 ngDialogProvider.setForceBodyReload(true);
567 ### ``.setOpenOnePerName({Boolean})``
570 Define whether or not opening a dialog with the same name more than once simultaneously is allowed. Assigning true prevents opening a second dialog.
572 Setting it in the ngDialogProvider:
574 var app = angular.module('exampleApp', ['ngDialog']);
576 app.config(function (ngDialogProvider) {
577 ngDialogProvider.setOpenOnePerName(true);
581 Make sure to remember to add a 'name' when opening a dialog.
582 **ngDialog 'open' and 'openConfirm' functions will return `undefined` if the dialog was not opened.**
586 By default the ngDialog module is served with the ``ngDialog`` directive which can be used as attribute for buttons, links, etc. Almost all ``.open()`` options are available through tag attributes as well, the only difference is that ``ng-template`` id or path of template file is required.
588 Some imaginary button, for example, will look like:
591 <button type="button"
592 ng-dialog="templateId.html"
593 ng-dialog-class="ngdialog-theme-flat"
594 ng-dialog-controller="ModalCtrl"
595 ng-dialog-close-previous>
600 You could optionally use ``ng-dialog-bind-to-controller`` to bind scope you've defined via parameter of directive to controller.
601 More information about bindToController is available [here](http://blog.thoughtram.io/angularjs/2015/01/02/exploring-angular-1.3-bindToController.html).
603 Directive contains one more additional but very useful option, it's an attribute named ``ng-dialog-close-previous``. It allows you to close previously opened dialogs automatically.
607 Everytime ngDialog is opened or closed we're broadcasting three events (dispatching events downwards to all child scopes):
609 - ``ngDialog.opened``
611 - ``ngDialog.closing``
613 - ``ngDialog.closed``
615 This allows you to register your own listeners, example:
618 $rootScope.$on('ngDialog.opened', function (e, $dialog) {
619 console.log('ngDialog opened: ' + $dialog.attr('id'));
623 ``ngDialog.closing`` is different than ``ngDialog.closed`` in that it is fired immediately when the dialog begins closing, whereas ``ngDialog.closed`` is fired after all animations are complete. Both will be fired even when animation end support is not detected.
625 Additionally we trigger following 2 events related to loading of template for dialog:
627 - ``ngDialog.templateLoading``
629 - ``ngDialog.templateLoaded``
631 In case you are loading your templates from an external location, you could use above events to show some kind of loader.
633 Finally, we trigger the following event when adding padding to or removing padding from the body tag to compensate for scrollbar toggling:
635 - ``ngDialog.setPadding``
637 The ``ngDialog.setPadding`` event will communicate the pixel value being added to the body tag so you can add it to any other elements in your layout at the same time (often fixed-position elements will need this).
642 Currently _ngDialog_ contains two default themes that show how easily you can create your own. Check ``example`` folder for demonstration purposes.
646 ngDialog supports accessible keyboard navigation via the ``trapFocus`` and ``preserveFocus`` options.
648 The ``role``, ``aria-labelledby`` and ``aria-describedby`` attributes are also supported, and are rendered as follows.
650 Dialog ``role`` attribute:
652 * ``options.ariaRole``, if specified
653 * "dialog" if ``options.ariaAuto`` is ``true`` and the dialog contains any focusable elements
654 * "alertdialog" is ``options.ariaAuto`` is ``true`` and the dialog does *not* contain any focusable elements
656 Dialog ``aria-labelledby`` attribute:
658 * ``options.ariaLabelledById``, if specified
659 * If ``options.ariaLabelledBySelector`` is specified, the first matching element will be found and assigned an id (if required) and that id will be used
660 * If ``options.ariaAuto`` is ``true``, the first heading element in the dialog (h1-6) will be found and processed as per ``ariaLabelledBySelector``
662 Dialog ``aria-describedby`` attribute:
664 * ``options.ariaDescribedById``, if specified
665 * If ``options.ariaDescribedBySelector`` is specified, the first matching element will be found and assigned an id (if required) and that id will be used
666 * If ``options.ariaAuto`` is ``true``, the first content element in the dialog (article,section,p) will be found and processed as per ``ariaDescribedBySelector``
668 Dialog Content ``role`` attribute:
670 * Always assigned a value of "document"
674 _ngDialog_ is available for public on [cdnjs](http://cdnjs.com/libraries/ng-dialog). For example, please use following urls for version ``0.4.0``.
677 //cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.4.0/css/ngDialog.min.css
678 //cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.4.0/css/ngDialog-theme-default.min.css
679 //cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.4.0/css/ngDialog-theme-plain.min.css
680 //cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.4.0/js/ngDialog.min.js
685 _ngDialog_ default styles are heavily inspired by awesome [Hubspot/Vex](https://github.com/HubSpot/vex) jQuery modals.
691 Copyright (c) 2013-2015, Likeastore.com <info@likeastore.com>
693 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
695 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
697 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
699 [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/likeastore/ngdialog/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
701 [contributor-guidelines]: https://github.com/likeastore/ngDialog/blob/master/CONTRIBUTING.md