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

15 Comments on “A Reusable AngularJS Popup Dialog Service”

  1. Pingback: AngularJS - Beginners guide / Yoosuf Muhammad

    1. 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

    2. 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.

      1. 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.support.cors.e.crossDomain.sendjquery-2.0.3.js:8829
        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

  2. 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 ?

  3. 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

    Thanks
    Dexter

  4. Praveen Vedanth

    Could you please explain ctrl object is being stored ?

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

  5. 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

    One:
    Tow:
    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/

      1. 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…

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

  7. Hemant Mali

    Hi,

    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();

    //});

Leave a Reply

Your email address will not be published. Required fields are marked *