0
votes

plunker: http://plnkr.co/edit/CrvOFHSfGnXFFWbaXNxn?p=preview

It seems scope for modal is not disposed of after closing the dialog. I have directive that emits when certain div is available, and modal controller receives it. It works fine on first open and close, one emit one receive. On 2nd dialog open and close, one emit and two receives, showing that there are two controller instances, and it goes on for any subsequent dialog open and close.

Is there anyway to make sure to dispose controller scope after modal dialog is dismissed?

html:

<!doctype html>
<html ng-app="ui.bootstrap.demo">
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.js"></script>
    <script src="example.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>

<div ng-controller="ModalDemoCtrl">
    <script type="text/ng-template" id="myModalContent.html">
        <div class="modal-header">
            <h3 class="modal-title">I'm a modal!</h3>
        </div>
        <div class="modal-body" my-hook>
            <ul>
                <li ng-repeat="item in items">
                    <a ng-click="selected.item = item">{{ item }}</a>
                </li>
            </ul>
            Selected: <b>{{ selected.item }}</b>
        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" ng-click="ok()">OK</button>
            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
        </div>
    </script>

    <button class="btn btn-default" ng-click="open()">Open me!</button>
    <button class="btn btn-default" ng-click="open('lg')">Large modal</button>
    <button class="btn btn-default" ng-click="open('sm')">Small modal</button>
    <div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
  </body>
</html>

js:

angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {

  $scope.items = ['item1', 'item2', 'item3'];

  $scope.open = function (size) {

    var modalInstance = $modal.open({
      templateUrl: 'myModalContent.html',
      controller: 'ModalInstanceCtrl',
      size: size,
      resolve: {
        items: function () {
          return $scope.items;
        }
      }
    });

    modalInstance.result.then(function (selectedItem) {
      $scope.selected = selectedItem;
    }, function () {
      $log.info('Modal dismissed at: ' + new Date());
    });
  };
});

// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.

angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $modalInstance, $rootScope, items) {

  $scope.items = items;
  $scope.selected = {
    item: $scope.items[0]
  };

  $scope.ok = function () {
    $modalInstance.close($scope.selected.item);
  };

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

  $rootScope.$on ('MyTestHook', function(event) {
    console.log("MyTestHook received");
  });
});

angular.module('ui.bootstrap.demo').directive('myHook', function($timeout,$rootScope) {
  function link(scope,element,attrs) {
    $timeout(function(){
     scope.$root.$emit("MyTestHook");
    },500);
  }

  return {
    link: link
  };
});
1

1 Answers

2
votes

This is not the problem of Modal. Modal scope is destroyed completely on dismiss.

Problem is in the code as you have attached $on on $rootScope so every time you click on model it add new listener in $$listeners and listener's count increased by one because $rootscope doesn't get disposed.

$rootScope.$on ('MyTestHook', function(event) { //every call to open modal will add new listener in rootscope
  console.log("MyTestHook received");
});

To avoid this use attach $on on scope that disposed on modal dismiss.

See below debugger image.

enter image description here

http://plnkr.co/edit/iR7rGCFgIchsk4sBg26Q?p=preview