How do I add a reusable modal dialog in Angular?

2019-04-07 20:32发布

问题:

I'm new to Angular and attempting to implement this solution into my project.

It looks painfully easy, however, I'm trying to make this into a re-usable element so that I can call it from anywhere and just pass in the content to be shown (otherwise, what's the point?).

So, my specific question is: assuming I already have a controller that's bound to some DOM element and it has a feature that goes and fetches some factory driven $http call and upon the response I wish to notify the user via this dialog of something, how do I combine *this directive and *this controller with my existing one and how do I do it in a way that allows me to then use it again from a totally different controller?

Or is this perhaps a bad example for this use and should I be looking at a different one?

回答1:

Compared to other options, below given the minimalist approach, using angular factory. See a sample snippet below.

Note: using Angular JS with UI Bootstrap - AngularUI.

  1. Reusable modal view - ConfirmationBox.html

<div class="modal-header">
  <h3 class="modal-title">{{title}}</h3>
</div>
<div class="modal-body">
  {{message}}
</div>
<div class="modal-footer">
  <button type="button" class="btn btn-primary btn-warn" data-ng-click="ok(); $event.stopPropagation()">OK</button>

  <button type="button" class="btn btn-default" data-ng-click="cancel(); $event.stopPropagation()">Cancel</button>
</div>

  1. Reusable module and shared factory, for handling the reusable modal dialog

angular.module('sharedmodule',['ui.bootstrap', 'ui.bootstrap.tpls'])
.factory("sharedService",["$q", "$modal", function ($q, $modal)
{
    var _showConfirmDialog = function (title, message)
    {
        var defer = $q.defer();

        var modalInstance = $modal.open({
            animation: true,
            size: "sm",
            templateUrl: 'ConfirmationBox.html',
            controller: function ($scope, $modalInstance)
            {
                $scope.title = title;
                $scope.message = message;

                $scope.ok = function ()
                {
                    modalInstance.close();
                    defer.resolve();
                };

                $scope.cancel = function ()
                {
                    $modalInstance.dismiss();
                    defer.reject();
                };
            }
        });

        return defer.promise;
    }

    return {

        showConfirmDialog: _showConfirmDialog
    };

}]);

  1. Portion of your View, using the shared modal dialog

<a data-ng-click="showConfirm()">Go Back to previous page</a>

  1. Controller of your view, opening your shared reusable modal dialog and handling notifications (Ok and Cancel)

var myModule = angular.module("mymodule", ['sharedmodule', 'ui.bootstrap', 'ui.bootstrap.tpls']);

myModule.controller('myController', ["$scope", "sharedService", "$window",
function ($scope, sharedService, $window)
{
    $scope.showConfirm = function ()
    {
        sharedService.showConfirmDialog(
            'Confirm!',
            'Any unsaved edit will be discarded. Are you sure to navigate back?')
            .then(function ()
            {
                $window.location = '#/';
            },
            function ()
            {
            });
    };
}]);



回答2:

Trying using 'ngDialog' library for popup and modal. Very good library. Later you can create a service which internally calls ngDialog functions. Later this service can be injected in your controllers for use. I have implemented this in one project.

The function in services can accept parameters for initialising the ngDialog modal.

Hope it helps :)



回答3:

for making it better I would suggest you to modify the code to look something as below

Template:

<div class='ng-modal' ng-show='modalContent != null && modalContent != ""'>
  <div class='ng-modal-overlay' ng-click='hideModal()'></div>
  <div class='ng-modal-dialog' ng-style='dialogStyle'>
    <div class='ng-modal-close' ng-click='hideModal()'>X</div>
    <div class='ng-modal-dialog-content' ng-transclude></div>
    <p>{{ modalContent }}</p>
  </div>
</div>

Directive:

app.directive('modalDialog', function() {
  return {
    restrict: 'E',
    scope: {
      modalContent: '='
    },
    replace: true, // Replace with the template below
    transclude: true, // we want to insert custom content inside the directive
    link: function(scope, element, attrs) {
      scope.dialogStyle = {};
      if (attrs.width)
        scope.dialogStyle.width = attrs.width;
      if (attrs.height)
        scope.dialogStyle.height = attrs.height;
      scope.hideModal = function() {
        scope.modalContent= null;
      };
    },
    template: '...' // See below
  };
});

and then use the code as below in template

<modal-dialog modal-content='modalMsg' width='750px' height='90%'></modal-dialog>

Once these changes are done you can write a function to set message in variable "modalMsg" and angular will take care of rest

Note: Code is pretty much the same as in the link, the only thing I have changed is the check to display the modal box