Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

angular-modal-service

Build StatusCoverage StatusDependenciesDev Dependencies

Modal service for AngularJS - supports creating popups and modals via a service. See a quick fiddle or a full set of samples at dwmkerr.github.io/angular-modal-service.

  1. Usage
  2. Developing
  3. Tests
  4. FAQ & Troubleshooting
  5. Thanks

Usage

Install with Bower (or NPM):

bower install angular-modal-service
# or...
npm install angular-modal-service

Then reference the minified script:

<scriptsrc="bower_components/angular-modal-service/dst/angular-modal-service.min.js"></script>

Specify the modal service as a dependency of your application:

varapp=angular.module('sampleapp',['angularModalService']);

Now just inject the modal service into any controller, service or directive where you need it.

app.controller('SampleController',["$scope","ModalService",function($scope,ModalService){$scope.showAModal=function(){// Just provide a template url, a controller and call 'showModal'.ModalService.showModal({templateUrl: "yesno/yesno.html",controller: "YesNoController"}).then(function(modal){// The modal object has the element built, if this is a bootstrap modal// you can call 'modal' to show it, if it's a custom modal just show or hide// it as you need to.modal.element.modal();modal.close.then(function(result){$scope.message=result ? "You said Yes" : "You said No";});});};}]);

Calling 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: close and 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:

app.controller('SampleModalController',function($scope,close){$scope.dismissModal=function(result){close(result,200);// close, but give 200ms for bootstrap to animate};});

The close function is automatically injected to the modal controller and takes the result object (which is passed to the close and 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.

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:

ModalService.showModal({templateUrl: "exampletemplate.html",controller: "ExampleController",inputs: {name: "Fry",year: 3001}})

injects the name and year values into the controller:

app.controller('ExampleController',function($scope,name,year,close){});

You can also provide a controller function directly to the modal, with or without the controllerAs attribute. But if you provide controller attribute with as syntax and controllerAs attribute together, controllerAs will have high priority.

ModalService.showModal({template: "<div>Fry lives in {{futurama.city}}</div>",controller: function(){this.city="New New York";},controllerAs : "futurama"})

ShowModal Options

The showModal function takes an object with these fields:

  • controller: The name of the controller to created. 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.
  • template: If templateUrl is not specified, you can specify template as 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.
  • appendElement: The custom angular element to append the modal to instead of default body element.
  • 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 $rootScope.

The Modal Object

The modal object returned by showModal has this structure:

  • modal.element - The DOM element created. This is a jquery lite object (or jquery if full jquery is used). If you are using a bootstrap modal, you can call modal on 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 close function 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 called close. Call this function with any parameter (the result). This result parameter is then passed as the parameter of the close and closed promises used by the caller.

Animation

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 class modal:

.modal.ng-enter {
transition: opacity .5s ease-out;
opacity:0;
}
.modal.ng-enter.ng-enter-active {
opacity:1;
}
.modal.ng-leave {
transition: opacity .5s ease-out;
opacity:1;
}
.modal.ng-leave.ng-leave-active {
opacity:0;
}

Error Handing

As the ModalService exposes only one function, showModal, error handling is always performed in the same way. The 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:

ModalService.showModal({templateUrl: "some/template.html",controller: "SomeController"}).then(function(modal){// only called on success...}).catch(function(error){// error contains a detailed error message.console.log(error);});

Developing

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 samples folder.

Tests

Run tests with:

npm test

A coverage report is written to build\coverage.

Debug tests with:

npm run test-debug

This will run the tests in Chrome, allowing you to debug.

FAQ

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 --><div>...some modal</div>

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:

modal.element.modal();

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 modal.element property.

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. All you need to do is grab the modal element in your controller, then call the bootstrap modal function to manually close the modal. Then call the close function as normal:

app.controller('ExampleModalController',['$scope','$element','close',function($scope,$element,close){$scope.closeModal=function(){// Manually hide the modal using bootstrap.$element.modal('hide');// Now close as normal, but give 500ms for bootstrap to animateclose(null,500);};}]);

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: modal.element.modal();. This occurs if you are using a Bootstap modal but have not included the Bootstrap JavaScript. The recommendation is to include the modal JavaScript before AngularJS.

Thanks

Thanks go the the following contributors:

  • joshvillbrandt - Adding support for $templateCache.
  • 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 body element changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages