Menu

#107 Clicking outside modal does not trigger close promise

open
nobody
None
2016-01-25
2015-09-21
Anonymous
No

Originally created by: Ape

Modals can be closed by clicking outside the modal window and I want to keep that functionality. However, closing the modal this way doesn't trigger the close promise.

Should it? Closing the modal with the close icon (X) on top right corner does trigger the promise. How do I know if the modal was closed by clicking outside of it?

Related

Tickets: #128

Discussion

  • Anonymous

    Anonymous - 2015-10-16

    Originally posted by: devourment77

    I ended up using angular events outside of ModalService.showModal to handle this. Basically setup a attribute directive on the body tag listening for non-modal clicks... and when it gets ones, broadcasts an event to close the modal, which is handled in our controller that invokes ModalService.showModal (not the modal controller itself). The reason for this is that (for whatever reason) I couldn't get broadcasted or emitted events working on within the modal controller (it wasn't hearing them at all).

    Hope it helps.

     
  • Anonymous

    Anonymous - 2015-10-23

    Originally posted by: MatteBailey

    I was having a similar problem, but was able to deal with it by watching for the Bootstrap 'hidden.bs.modal' event. Essentially:

    ModalService.showModal({
                  ...
        }.then(function(modal) {
            modal.element.on('hidden.bs.modal', function () {
                modal.controller.closeModal();
            });
    }
    
     
  • Anonymous

    Anonymous - 2016-01-04

    Originally posted by: tiagomsmagalhaes

    @devourment77 can you provide a fiddle?

    @MatteBailey can you also provide a plunkr please. I tried to use your snippet but the snippet seems to be activated every time because the buttons also will hide the modal so the that function would be passed on every click. Also closeModal is not a function so you probably defined that one?

    thank you all in advance.

     
  • Anonymous

    Anonymous - 2016-01-22

    Originally posted by: ghost

    Yeah please provide at least something, since above ain't working for me, would love quickfix for this issue)

     
  • Anonymous

    Anonymous - 2016-01-23

    Originally posted by: MatteBailey

    I've added to this since my first comment in October. Hopefully the code below is helpful:

    In whatever controller you're using ModalService in:

    ModalService.showModal({
        templateUrl: "exampleTemplate.html",
        controller: "ExampleController",
        controllerAs: "ctrl"
    }).then(function(modal) {
        modal.element.one('hidden.bs.modal', function () {
            if (!modal.controller.closed) {
                modal.controller.closeModal();
            }
        });
        modal.element.modal();
    });
    

    And then in ExampleController:

    this.closed = false;
    
    this.closeModal = function () {
        close(null, 200);
        this.closed = true;
    }
    

    And in exampleTemplate.html

    <button ng-click="ctrl.closeModal()" type="button" class="btn btn-default">Cancel</button>
    

    This addresses the issue you mentioned @tiagomsmagalhaes. If you click the "Cancel" button, this.closed (which is modal.controller.closed in your first controller) will become true, and when you catch hidden.bs.modal you won't trigger closeModal again.

    Definitely a work around, but it does the job with only a few extra lines.

    Make sense?

     
  • Anonymous

    Anonymous - 2016-01-23

    Originally posted by: ghost

    Thx man, it's great fix indeed!!

     
  • Anonymous

    Anonymous - 2016-01-24

    Originally posted by: tiagomsmagalhaes

    thanks for the reply @MatteBailey. Meanwhile i got it to work as described in [#128]. I don't know if it's more elegant than your solution. I just added the failed promise part to catch the event. I think although the hidden.bs.modal is in the failed promise section, it's being called every time which isn't so problematic but i think it's not elegant.

     

    Related

    Tickets: #128

  • Anonymous

    Anonymous - 2016-01-25

    Originally posted by: MatteBailey

    Hi @tiagomsmagalhaes ,

    If you want to run that code in the error callback of modal.close, you would do something like this:

    modal.close.then(function(result) {
        $scope.yesNoResult = result ? "You said Yes" : "You said No";
    }, function () {
        modal.element.on('hidden.bs.modal', function() {
            $('.modal').remove();
        });
    });
    

    I don't think this will help us though, because modal.close doesn't get rejected when a user clicks outside the modal to close it.

    We generally provide an anonymous function for the promise callbacks. Since you're invoking modal.element.on(), it does indeed get run every time. I think what you have will behave the same as doing this:

    modal.close.then(function(result) {
        $scope.yesNoResult = result ? "You said Yes" : "You said No";
    });
    
    modal.element.on('hidden.bs.modal', function() {
        $('.modal').remove();
    });
    

    This will definitely work for removing the modal from the DOM, but we will never resolve modal.close, which is problematic. This is the what my solution above addresses.

    Let me know if I'm misunderstanding anything!

     

Log in to post a comment.