9

I'm creating a mailbox in angular. And I would need to save the draft message when the popup to send a message closes.

I know there are some alternatives:

scope.$on("$destroy", function () { saveMessage() });

and:

$mdDialog.show(...).finaly(function(){ saveMessage() });

But both are insufficient:

  • The first is called when the Dialog is already closed. This is due to the requirements unacceptable (there is an iFrame that needs to be open)
  • The second is outside the scope of the controller of the mdDialog, and gives the responsibility to the caller of the pop-up, while it should be in the pop-up itself.

So I'm looking for way to call a function BEFORE the pop-up actually closes. Something like scope.$on("$mdDialogBeforeClose", function () { saveMessage() });

Another option would be to hook every close event. Seems ugly, but might be the solution. In that case I would need to listen to the escape-button and clicking outside the pop-up (Altough I might disable that function)...

Any better ideas?

Thx!

EDIT:

An addition question: How to catch the escape-keypress event? I tried <md-dialog aria-label="List dialog" ng-keypress="keyPress($event)"> but it's not even triggered...

Thomas Stubbe
  • 1,945
  • 5
  • 26
  • 40

2 Answers2

10

Maybe use the onRemoving callback - CodePen

From the docs:

enter image description here

Markup

<div ng-controller="MyController as vm" id="popupContainer" ng-cloak="" ng-app="app">
   <md-button class="md-primary md-raised" ng-click="vm.open($event)">
      Custom Dialog
    </md-button>

  <script type="text/ng-template" id="test.html">
    <md-dialog aria-label="Test">
        Hello!
    </md-dialog>
  </script>
</div>

JS

angular.module('app',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])

.controller('MyController', function($scope, $mdDialog) {
  this.open = function(ev) {
    $mdDialog.show(
      {
        templateUrl: "test.html",
        clickOutsideToClose: true,
        onRemoving: function (event, removePromise) {
          console.log(123);
        }
    });
  };
})
camden_kid
  • 12,591
  • 11
  • 52
  • 88
  • This has the same issues as the second case I described. I need to be in the controller of the modal. I need to access that scope, and I would like to have the modal itself the responsibility to save the message on every close (we're a team of developers, and there are multiple places where the dialog opens) – Thomas Stubbe Sep 29 '16 at 09:45
  • @ThomasStubbe The demos show how to close the dialog with a function in the dialog controller. Do you mean closing the dialog by clicking outside? – camden_kid Sep 29 '16 at 10:14
  • The demo doesn't use a dialog controller at all: `controller: SomeDialogController` should be added to the show-function. Inside that controller there is a function that needs to be executed before close. – Thomas Stubbe Sep 29 '16 at 10:22
  • @ThomasStubbe I'm a bit confused :-) Does this work for you? - http://codepen.io/camden-kid/pen/rrzOLP?editors=1010#0 – camden_kid Sep 29 '16 at 10:39
  • 1
    This is what I want, except that the close function should also be triggered when escape is pressed, or clicked outside the dialog. So I want to call that close function in any case when the dialog closes. The two ways to do that I described in my question, but they are either outside the scope of the dialogController (`finally`), or after the HTML is already destroyed (`scope.$on('$destroy')`) – Thomas Stubbe Sep 29 '16 at 11:10
  • 1
    @ThomasStubbe Would something like this help? - http://codepen.io/camden-kid/pen/rrzOLP?editors=1010 – camden_kid Sep 29 '16 at 11:40
  • This is indeed a possibility that I haven't considered yet, and would do the job =) But I'm afraid I can't use it though: I have 2 concrete DialogControllers, depending on the type of message, and they extend from another BaseDialogController. Each is over 200 lines, and I call the `show()` from different places, so I cannot just pass the scope to the DialogController, this would bring a lot of issues. Do you know of a way to do this, but with a new scope for the DialogController, instead of passing him? – Thomas Stubbe Sep 29 '16 at 12:06
  • I might be able to create a new scope before calling the `show()`: `$rootScope.Scope([providers], [instanceCache]);` – Thomas Stubbe Sep 29 '16 at 12:12
  • @ThomasStubbe How about using a service? http://codepen.io/camden-kid/pen/vXJKOX?editors=1010 – camden_kid Sep 29 '16 at 12:18
  • I need to access functions of that scope in beforeClose() action... There are rest calls (like 4 of them in a row) that need the scope of the mdDialog... This works: `var scope = model.$new(true);` and `$mdDialog.show({ ... onRemoving: function() { scope.onDestroy().then(function () { }); }, ...` But now I need to find a way to prevent the return of the function until the promise returns – Thomas Stubbe Sep 29 '16 at 12:33
  • @ThomasStubbe Sorry I couldn't help. Good luck. – camden_kid Sep 29 '16 at 12:37
  • @ThomasStubbe Why do you need to prevent the function from returning? With `preserveScope: true` I'd expect the functions to still work after closing. Or do you want to prevent closing in certain situations? In this case, re-opening the modal would be an idea. – fishbone Apr 12 '21 at 10:00
3

Dialog return a promise using that you can handle dialog close event

var dialogPromise  = $mdDialog.show(
      {
        templateUrl: "test.html",
        clickOutsideToClose: true,
        onRemoving: function (event, removePromise) {
          console.log(123);
        }
    });

dialogPromise.then(function(){
   // hide method handler
   // You can write your code here that execute after dialog close
}, function(){

});
Dipten
  • 1,031
  • 8
  • 16