A Reusable AngularJS Popup Dialog Service

At Fundoo Solutions, we found ourselves having the need to show popup dialogs in the multitude of projects we have worked on. We always ended up using Twitter bootstrap, and we loved their modal dialogs. But we found it very restrictive, or needing a lot of customization to make it look and behave how we wanted it to. So, we took their CSS, and added our own functionality, and ended up with what we are calling AngularJS Popup Dialog or AngularJS Modal Service.

Why create the AngularJS Popup Dialog Service?

As we mentioned, we found ourselves redoing the same stuff again and again. Style the contents differently, need a different controller on each modal, pass in some content to the modal to display it, etc. We thought of making it a directive, but that had its own implications. We ended up making it a service, because:

  1. We didn’t want to pollute the DOM with the modal content unless the modal was to be displayed. So we defer it till the point the service is called.
  2. Passing the data into the modal with a directive would need custom attributes (that would differ from modal to modal). That would also imply the data would have to be put on the scope before it could be passed in, which is not always convenient.

How do I use it?

We export the service ‘createDialog‘ as part of the ‘fundoo.services‘ module. We can then call the createDialog service as a function directly, passing in the following arguments

createDialog(templateUrl, otherOptions, argumentsForController)

Thats about it. You will need

  • Bootstrap CSS
  • jQuery

When this function is called, a modal is poped up, with the template specified in the template URL becoming the body of the modal dialog. What else you can change and pass to the service in otherOptions and argumentsForController is covered in the next section. This is what happens when you call the service:

AngularJS Popup Dialog Screenshot

What can I change?

In addition to modifying the template body, with the AngularJS Popup Dialog service, you can change the

  • ID of the dialog (and the class for the modal)
  • Title at the top of the dialog
  • Whether or not to show a backdrop behind the popup (and the class to use for the backdrop)
  • The template for the footer (so that you can change what buttons to show)
  • The function to call on success!
  • A controller to attach to the modal

In addition, as part of the third argument, you can pass an object with keys and values. Each key can then be accessed through the controller’s constructor arguments.

Can I see it in action?

Sure. Go ahead take a look at the example here.

Where can I learn more?

We have open-sourced this code (the first of many more to come soon, we promise!) and it is now available for your perusal and reuse at this link. Feel free to use it as it is, or modify the heck out of it. Do let us know if you like it, and feel free to send us a pull request if you have some changes which you think everyone can benefit from.

ShyamA Reusable AngularJS Popup Dialog Service
  • Pingback: AngularJS - Beginners guide / Yoosuf Muhammad()

  • B Shankar J

    How can I do the form submit in this?

    • http://www.befundoo.com Shyam

      You should be able to use the ng-submit directive in the form as part of the template, and refer to functions in the controller

    • http://theshyam.com/ Shyam Seshadri

      You should be able to just have a inside the modal template and it should happen. You will have to use ng-submit to get a notification on form submit, and run it through angularjS.

      • Rajiv Chaudhuri

        The form submission does not work if I use HTTPS. I am using jQuery form inside the template and when I submit the form I am getting following error-
        x.extend.ajax jquery-2.0.3.js:8829
        $.fn.ajaxSubmi jquery.form.js:245
        $scope.login LoginController.js:24
        (anonymous function) angular.js:9067
        (anonymous function) angular.js:16515
        g.$eval angular.js:10699
        g.$apply angular.js:10796
        (anonymous function) angular.js:16514
        x.event.dispatch jquery-2.0.3.js:8829
        y.handle jquery-2.0.3.js:8829

  • Anudeep

    Does it work well on mobile ? I am having problems displaying on mobile with my current modal design .Just wanted to know if your version of modal dialogs works good on mobile ?

    • http://theshyam.com/ Shyam Seshadri

      It works on mobile, and displays well (Tested on Chrome on Android).

      You will have to work with the CSS and styles to make it the right side, but I don’t see why it shouldn’t.

      Try opening http://fundoo-solutions.github.io/angularjs-modal-service/ to get a feel for it. I haven’t added the viewport meta to make it resize properly, but if you zoom out, and try it out, it does work.

  • Dexter

    I have attached a controller to the ComplexDialog, how do I load $scope variables in the template ex: {{title}} but this doesn’t work


  • Praveen Vedanth

    Could you please explain ctrl object is being stored ?

    modalEl.contents().data(‘$ngControllerController’, ctrl);

  • Eugeniu Rata

    There is a big issue with this implementation. Here is how to simulate

    in the demo controller you have add these 2 lines

    $scope.message = “”;
    $scope.test = function(){ console.log($scope.message); }

    now change the complexModal.html by adding these 3 lines somewhere in the code

    Click Me

    now, when we change the text in either of the textboxes it displays ok, however when we click on the button we see that the message is actually empty. By this I’m assuming the ‘message’ variable goes into a different scope.

    Any ideas?

    The correct behavior is shown in this simple demo http://jsfiddle.net/Ad6N4/1/

    • Eugeniu Rata

      Sorry for the wrong link, here is the correct one http://jsfiddle.net/Ad6N4/3/

      • outsider

        It is because they add an ng-include for url templates. And ng-include generates a new scope… So is not a good use of ng-include. So the controller at the end has a X scope, the header and footer have X scope, and the body, if is by url has Y scope, otherwise has X scope too…

  • Александр Шумахер

    memory leak in your solution, Shyam

    • Justin Goltermann

      Can you please clarify? Do you mean that there’s a problem with the modal code not cleaning up after itself?

  • Pingback: Learning AngularJS – best resources to learn angularjs for beginners. | Bhavin Patel()

  • Hemant Mali


    I have used the createDialog service on in my controller to show the popuop when user hit delete.Now I want test that using jasmine how do I do that?

    Does anyone know how to test that servic?Please Help.

    $scope.deleteProject = function (id) {

    createDialog(‘/App/Modules/ReadAdmin/Projects/Templates/deleteproject.html’, {

    id: ‘DeleteProjectDialog’,

    title: ‘Delete Project’,

    backdrop: true,

    controller: ‘DetailCtrl’,

    success: { label: ‘Proceed’, fn: function () { projectService.delete({ id: id }); } },

    cancel: { label: ‘Cancel’, fn: function () { console.log(“Delete modal closed”); } }



    id: id



    //Details controller

    projectApp.controller(‘DetailCtrl’, function ($scope, projectService, id) {

    $scope.project = projectService.get({ id: id });


    //This is my test

    it(‘should delete the project’, function () {

    // $httpBackend.expectGET(api/projects).respond([{ id: 100, code: “B100″, “name”: “ABC”}]);

    // $httpBackend.expectDELETE(api/projects/100′).respond({});

    // var ctrl = $controller(‘DetailCtrl’, { $scope: $scope, projectService: mockprojectService,createDialog:dialogService });

    // $scope.deleteProject(100);

    // $httpBackend.flush();

    // expect(mockprojectService.delete).toHaveBeenCalled();


  • Reena Singh
    • Anil Singh

      Thanks @disqus_veugykDnv6:disqus, This link is very useful for me.

  • Justin Goltermann

    Hey, heads-up: there’s a significant bug in your code! This line:

    var body = $document.find(‘body’);

    …Should not be taking place outside your returned Dialog function. By placing this line outside your code is effectively caching a copy of the BODY element. That’s OK if your code is only ever going to work on a single instance of a page, and the user will never ever leave this page and come back to it. However, the moment a user does the modal will not attach to the BODY element correctly… because the BODY element in question is a cached copy of an element that no longer exists in the DOM. In other words, it has no connection to the BODY element currently on the page, and all further attempts to render to modal will seem to do nothing whatsoever.

    The solution?

    Include it *within* the Dialog function definition. This ensures it’s always going to grab the correct DOM reference.

    Hope this helps someone else. BTW, love the plugin, it kicks butt! :)