9

I'm invoking a bootstrap modal dialog through a link.

I want to start a timer in the angular controller when the dialog pops up. How do I detect the dialog open event in the angular controller to start the timer?

If I start timer in the scope like this,

app.controller('myctrl',
    ['$scope', '$window', '$timeout', 'svc',
    function ($scope, $window, $timeout,  svc) {

        $scope.countdown = 10;

        $scope.runCounter = function () {
            $scope.countdown -= 1;
            if ($scope.countdown > 0)
                $timeout($scope.runCounter, 60000);
       }
        $scope.runCounter();
    }]);

the timer starts when the application starts. I want the timer to start only when the dialog opens. Thanks.

4 Answers 4

78

Check this out.

var modalInstance = $modal.open({...});
modalInstance.opened.then(function() {
    alert("OPENED!");
});

The $modal.open() returns an object that, among other properties contains the opened promise, to be used as above.

Sign up to request clarification or add additional context in comments.

7 Comments

This is the correct answer, should be the accepted answer. Ashish's answer above is really more of a hack
What if it's not opened ? It'll give 'TypeError: Cannot read property 'opened' of undefined' ? Do you have a solution for that ?
If there is a chance the modal will not open, just add an if( modalInstance ) before the line.
I wanted to use this to focus on the element in the modal, but it looks like even the opened event is not late enough, so i hacked it by setting a 200 ms $timeout in the opened event
Use the rendered event rather than opened if you need access to the DOM inside the modal dialog.
|
4

I assume that you are using modals from http://angular-ui.github.io/bootstrap/.

If you look closely you will see that the component expose a promise that will be resolved when the dialog is opened. Which is what you will need to use. You can do something like that in the controller where the modal is created:

$scope.runCounter = function () {
  $scope.countdown -= 1;
  if ($scope.countdown > 0)
    $timeout($scope.runCounter, 60000);
}

//Creating the dialog
var modalInstance = $modal.open({
  templateUrl: 'myModalContent.html',
  controller: ModalInstanceCtrl
  }
});

//Add a function for when the dialog is opened
modalInstance.opened.then(function () {
  $scope.runCounter 
});

See working plunker here

1 Comment

Tried the same. But $modal is not opening the dialog. Isn't it possible to call $modal from an angular service? $modal.open({ template: "<p>{{countdown}}</p>", controller: 'myctrl' }); controller is instantiated but dialog not opening.
0

 var modalInstance = $modal.open({
                templateUrl: '../augustine_app/templates/program_purchase_popup.html',
                backdrop: 'static',
                controller: function ($scope, $modalInstance) {
                    $scope.cancel = function () {
                        $modalInstance.dismiss('cancel');
                    };
                }
            });

            

            if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
                modalInstance.opened.then(function () {
                    var modal;
                    var getModalInterval = function () {
                        modal = document.getElementsByClassName('modal')[0];
                        if (modal) {
                            clearInterval(getModal);
                            modal.style.marginTop = window.screenTop + 'px';
                            modal.style.height = 'auto';
                            modal.style.position = 'absolute';
                            modal.style.overflow = 'visible';
                        }
                    };
                    modal = document.getElementsByClassName('modal')[0];
                    if (!modal) {
                        var getModal = setInterval(getModalInterval, 2000);
                    }
                });
            }
        };

Unfortunatly the open.then(func) runs before the freaking modal is actually in the DOM. Hence the setInterval.

here is some non jQuery angular code.

Comments

0

For my case, I need to be able to detect when modal is opened inside the modal controller itself.

At first opened promise was resolved even though the modal hasn't been loaded in the DOM yet. By wrapping the call inside a $timeout, opened promise is now resolved after the modal is loaded to the DOM.

$modal.open({
  templateUrl: 'modalTemplate.html',
  controller: 'modalCtrl'
});

// inside modalCtrl
angular.controller('modalCtrl', ['$modalInstance', '$timeout', function($modalInstance, $timeout) {
  $timeout(function() {
    $modalInstance.opened.then(function() {
      //do work
    });
  });
}]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.