AngularUI Bootstrap Modal Open event - angularjs

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.

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.

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

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.

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
});
});
}]);

Related

How to deal with modal controller outside AngularJs module?

My app uses Angular UI to deal with modals and I think I found a problem, as below:
I have a controller that calls the modal controller:
angular.module('MyApp').controller('MainCtrl', function ($scope, $modal) {
$scope.openModal = function () {
var myModal = $modal.open({
animation: true,
templateUrl: 'ModalContent.html',
controller: ModalCtrl
});
};
});
I also have the modal controller in another file, as a simple function:
function ModalCtrl ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
It's working well, but I think the modal controller have to be inside AngularJs module. The questions are:
Can I do it and keep the modal controller in a separated file?
It's a good practice keep the modal controller outside AngularJs module?
What is the best practice to reuse a modal controller in many pages?
Thanks a lot!
That object you're passing into $modal.open() can be registered as a shared service and the modal controller can be embedded right inside it.
angular.module('myApp').factory('myModalConfig', function() {
return {
animation: true,
templateUrl: 'ModalContent.html',
controller: function($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}
};
});
Then just inject that along with the $modal service and pass it.
angular.module('MyApp').controller('MainCtrl', function ($scope, $modal, myModalConfig) {
$scope.openModal = function () {
var myModal = $modal.open(myModalConfig);
};
});
I go further than this myself and wrap the whole thing into a custom modal service factory, so I can just inject one thing and open modals like this: profileModals.editProfile(). But that's beyond the scope of this answer.

AngularJs close modal

I wan create function to close modal . I try some thing like this .
Code for open the modal
$scope.showPreloader = function() {
$scope.$modalInstance = $modal.open({
animation: false,
templateUrl: preloaderTemplate,
size: 'sm',
windowClass: 'preloader',
})
};
To hide modal
$scope.hidePreloader = function() {
$scope.$modalInstance.dismiss('cancel');
};
The modal only open and not close it . I run them like this .
$scope.simulateLoader = function(message) {
var runIns = $scope.showPreloader();
setTimeout(function () {
$scope.hidePreloader();
}, 2000);
}
The close function didn't work.
Edit: I think the close function is run . It only not remove the modal . I set backdrop to false . Backdrop cant be click during that time out .
Use Angular $timeout instead of window.setTimeout, because $timeout will call $scope.$apply to trigger $digest and update the view:
$timeout(function () {
$scope.hidePreloader();
}, 2000);
Remember to inject $timeout when declaring the controller, say:
app.controller('MyCtrl', ['$scope', '$timeout', function ($scope, $timeout)...
Try like this :
$scope.showPreloader = function() {
$scope.$modalInstance = $modal.open({
animation: false,
templateUrl: preloaderTemplate,
size: 'sm',
windowClass: 'preloader',
scope: $scope,
controller: ['$scope','$modalInstance', function ($scope, $modalInstance) {
$scope.hidePreloader = function () {
$modalInstance.dismiss('cancel');
};
}
})
};
and then call your $scope.hidePreloader method to dismiss modal popup

How to see whether modal is open in Angular UI Bootstrap

I'm using Angular UI Bootstrap. If a modal is open, I'd like to display true. If it's not open, I'd like to display false. Is there a way to do this within the HTML?
I tried using the following code, but it's wrong:
<code>myForm.$modalStack.opened={{myForm.$modalStack.opened}}</code>
Any thoughts on how to do this correctly?
Below the relevant code I'm using to trigger the modal:
HTML:
<button ng-click="myForm.agreement()">
Code in Controller:
.controller('MyFormCtrl',
function ($location, $stateParams, $modal, $scope, $http) {
var myForm = this;
// . . .
myForm.agreement = agreement;
function agreement() {
$modal.open({
templateUrl: 'views/agreement.html'
})
});
The opened property returned by $modal.open is a promise you can hook into.
So, using their example, see here - http://plnkr.co/edit/PsEqTIy8CDUU88HMLxbC?p=preview
$scope.modalOpen = false;
$scope.open = function (size) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.opened.then(function () {
$scope.modalOpen = true;
});
// we want to update state whether the modal closed or was dismissed,
// so use finally to handle both resolved and rejected promises.
modalInstance.result.finally(function (selectedItem) {
$scope.modalOpen = false;
});
};
You want to call the promises and then do whatever you need. .opened is a promise for when the modal opens, and .result is a promise for when the modal closes. So using this idea, you would use $scope.modalOpen as your boolean.

How to close Angular UI Modal from anywhere

I am using the Angular UI bootstrap modal dialog and create it within a service:
myApp.factory('ModalService', ['$modal', function($modal) {
return {
trigger: function(template) {
$modal.open({
templateUrl: template,
size: 'lg',
controller: function($scope, $modalInstance) {
$scope.ok = function() {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
});
},
close: function() {
// this should close all modal instances
}
};
}]);
How can I close all modal instances when calling ModalService.close() from a controller or whatsoever?
Inject the $modalStack service and call the function $modalStack.dismissAll(), see the code on GitHub for details:
myApp.factory('ModalService', ['$modal', '$modalStack' function($modal, $modalStack) {
return {
trigger: function(template) {
$modal.open({
templateUrl: template,
size: 'lg',
controller: function($scope, $modalInstance) {
$scope.ok = function() {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
});
},
close: function(reason) {
$modalStack.dismissAll(reason);
}
};
}]);
I added the below line to prevent browser back button routing and closing the popup. We need to inject $modalStack into angular controller.
event.preventDefault();
$modalStack.dismissAll('close');
This is how i got it working in my project without using any factory or additional code.
//hide any open $mdDialog modals
angular.element('.modal-dialog').hide();
//hide any open bootstrap modals
angular.element('.inmodal').hide();
//hide any sweet alert modals
angular.element('.sweet-alert').hide();
I have a timeout function that emits logout as $rootScope.$emit('logout'); and the listener in my service is as follows:
$rootScope.$on('logout', function () {
//hide any open $mdDialog modals
angular.element('.modal-dialog').hide();
//hide any open bootstrap modals
angular.element('.inmodal').hide();
//hide any sweet alert modals
angular.element('.sweet-alert').hide();
//do something else here
});
I don't know if this is the right approach , but it works for me.

Angular UI Bootstrap Modal, bind model changes immediately

I am trying to use Angular UI Bootstrap Modal. And I want to have the changes to the model to be shown immediately.
This is the controller:
$scope.testInputField = "";
$scope.showModal= function () {
var modalInstance = $modal.open({
templateUrl: 'partials/modal.html',
controller: 'ModalController',
resolve: {
inputTest: function () {
return $scope.testInputField;
}
}
});
modalInstance.result.then(function () {
// Do stuff
}, function () {
console.log("Some Error");
});
}
I have testInputField model also in my partial view.
And this is the the modal controller
controller('ModalController', [ '$scope', '$modalInstance', 'inputTest', function ($scope, $modalInstance, inputTest) {
$scope.inputTest = angular.copy(inputTest);
$scope.keyPressed = function (key) {
$scope.inputTest+= key;
console.log($scope.inputTest);
};
} ])
So basically what I want whenever changes are made to with the keyPressed method, the modal in my main controller to be changed at the same time. Is there a possibility to accomplish this with UI bootstrap modals current code
For this remove angular.copy method and try again. As it remove the data binding of the object.

Resources