0

When I create a modal, with a dynamic message that is fetched from the server (not sure this is relevant), the modal opens fine with the message. However, if I fail one more time and the modal is created again it will show two modals, and if I fail one more time it will show three different modals that I have to close with the "Close"-button.

My thoughts is that this is some $scope-related issue that I've screwed up somehow but I can't figure out how to fix it, or that the $modalInstance.dismiss() does not work as it should.

I'm using angular-ui to get access to $modal.

I have created a ModalsFactory that is called whenever I want to create a modal. As you can see I have an openModal-function that holds the modal-code and three other functions that call this depending on which modal to show:

angular.module('tsModule')
    .factory('ModalsFactory',
    function ($modal) {
        return {
            openModal: function(template, message) {
                console.log("OPENING");
                $modal.open({
                    templateUrl: template,
                    controller: function($scope, $modalInstance) {
                        $scope.message = message;
                        $scope.cancel = function () {
                            $modalInstance.dismiss();
                        };
                    },
                    size: 'm'
                });
            },
            openSuccessModal: function(message) {
                this.openModal('/static/partials/modals/modal_success.html', message);
            },

            openFailedModal: function(message) {
                this.openModal('/static/partials/modals/modal_failed.html', message);
            },

            openInfoModal: function(message) {
                this.openModal('/static/partials/modals/modal_info.html', message);
            }
        };
    }
);

This can be opened by a $broadcast:

$rootScope.$on(AUTH_EVENTS.loginFailed, function(e, res) {
    console.log("LOGIN FAILED");
    ModalsFactory.openFailedModal(res.message);
});

And this $broadcast can be triggered by if the server returns an error-code by some sort:

console.log("CALLING $BROADCAST");
data.message = "Felaktiga inloggningsuppgifter.";
$rootScope.$broadcast(AUTH_EVENTS.loginFailed, data);

What I have found out so far is: The OPENING-console text will shown as many times as the number of modals shown The LOGIN FAILED-console text will be shown as many times as the number of modals shown The CALLING $BROADCAST-console text will only be shown once

I've found someone with the exact same problem as me but not using Angular here

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
jwanglof
  • 548
  • 1
  • 5
  • 20
  • 1
    WHere is your code that has `$rootScope.$on(AUTH_EVENTS.loginFailed` ? If you are registering this multiple times, they add up and will be called as many times. – PSL Aug 03 '14 at 16:48
  • @PSL That code is in a login-function. If I put a console.log() in there it will only be shown once but the modals keeps adding up. Code: http://pastie.org/9441841 – jwanglof Aug 03 '14 at 16:52
  • How many times you call login function? before any scope is destroyed? Try put a log on `$rootScope.$on('$destroy', function...)` and see if this log is equal in number to the number of logs logged by event registration? – PSL Aug 03 '14 at 16:55
  • As @PSL pointed out, try moving the `$rootScope.$on` out of `login()` function. The `$rootScope.$on` should be called once, not everytime the `login()` function is called. – runTarm Aug 03 '14 at 17:03
  • @runTarm Where should I put the $on-call? This is how the factory looks right now: http://pastie.org/9441866 . I can't really figure out how to do this. – jwanglof Aug 03 '14 at 17:11
  • Try putting it at the beginning of the `AuthService` factory function, just before the `return {` statement. – runTarm Aug 03 '14 at 17:12
  • @runTarm Cool! That works beautifull. So should I move all $broadcast.$on outside return? – jwanglof Aug 03 '14 at 17:21
  • It depends. If the event should be listened for the life time of the app, it's fine to put `$on` there. But if the event handler should be executed only once after some action, put `$on` inside that action and unsubscribe it after executed. – runTarm Aug 03 '14 at 17:27
  • @runTarm I only want the listeners to do one thing, i.e. open a modal. So is this the correct way to do it? When I try this it will only open one modal at a time. My code right now: http://pastie.org/9441898 – jwanglof Aug 03 '14 at 17:37
  • That's ok, as long as the `login()` function cannot be called again before the result of the first call is done. – runTarm Aug 03 '14 at 17:41
  • Awesome, thanks so much to @runTarm and @PSL! – jwanglof Aug 03 '14 at 17:43

1 Answers1

0

You are creating a new modal every time the modal generation event is broadcasted. $modalInstance.dismiss() should just hide the modal and not remove/destroy the modal. I think you need to use $modalInstance.close($scope.selected.item) instead of dismiss.

rbaljinder
  • 56
  • 3
  • 1
    Both `close()` and `dismiss()` will remove the modal, the only different is that `close()` will resolve a result promise, but `dismiss()` will reject it. – runTarm Aug 03 '14 at 16:58