How do I close an $ionicPopup before opening a new one? - angularjs

I'm creating an Ionic application with a form and some required fields.
When the form is submitted and if it isn't valid, I display an alert message using Ionic's $ionicPopup service.
My problem is: the user can press "ENTER" or ("Go" button within Android) to both invoke form submission and close the popup which causes another popup to open.
You can see this happening here:
Sample Code
Focus the input, press ENTER and when the error message is displayed, press ENTER again to close it. Another popup will open (most likely because the input behind the backdrop still has focus or maybe because the modal is created within the form - having ENTER invoke submit again).
Is there any way to avoid that behavior? Maybe the ENTER within the $ionicPopup to close it without submitting the form again, or at least having some code to close any active popups before displaying a new one? Because when you open multiple popups, if you try the mouse (or tap) to close a message, the user is prompted to then close all other dialogs before being sent back to the main screen.
I know I could try to get the reference to the popup and call the close() method but it didn't quite work for me. Eventually the new alert opens before the previous one is fully closed and the backdrop gets stuck on the screen forever.
Thanks for helping.

As it turns out, my actual problem is that the $ionicPopup does not support pressing ENTER (or "go" on Android keyboard) to close the popup. For some reason, I tried to take the focus out of the inputs but it didn't work.
For anyone with the same problem, I ended up creating an angular directive to close the device keyboard when the form is submitted.
Here's the directive code:
(function () {
'use strict';
angular
.module('myModule')
.directive('closeKeyboardOnSubmit', closeKeyboardOnSubmit);
closeKeyboardOnSubmit.$inject = ['$ionicPlatform', '$cordovaKeyboard'];
function closeKeyboardOnSubmit($ionicPlatform, $cordovaKeyboard) {
var directive = {
require: '^form',
restrict: 'A',
link: link
};
return directive;
function link (scope, element) {
element.on("submit", function(){
$ionicPlatform.ready(function(){
$cordovaKeyboard.close();
});
});
}
}
})();
then I used it on the form tags like this:
<form close-keyboard-on-submit ...>
Obviously the problem still happens when testing directly on the browser but works when deploying to the devices.

Related

Angularjs UI-Router state change changes functionality of Google-API directive

I am using a google places autocomplete directive: vs-google-autocomplete
which works fine. The problem is, if we change the $state (by back / forward button, or just ui-sref="testroute", or $state.go()), it suddenly does not work the way it worked before.
I set up a plnkr:
google.maps.event.addListener(autocomplete, 'place_changed', function() {
console.log("place_changed");
});
google.maps.event.addDomListener(element[0], 'keydown', function(event) {
if (event.keyCode == 13 || event.keyCode == 9)
console.log("keydown");
});
http://plnkr.co/edit/wbhEWds1pY1bWrguV40U?p=preview
You can enter an address and just hit enter. Then open the console. You will see:
keydown
place_changed
but if you now click on route2 and then back on route1, enter another address and press the enter button, console will log:
place_changed
keydown
The order of the eventhandlers changed. It seems that google search / - functionality is somehow broken, when google is loaded once, then the $state changes and you again try to use google.
Also, there is a second .pac container in the dom, and I guess google is somehow loaded twice or something while the controller just reloads.
Do you know why this behaviour happens and how I can prevent that or do you have at least an idea on how to workaround this problem? I need keydown to be before place_changed. The google search still works in the plnkr, but it is buggy a bit. I think it is a problem with angularjs/$state loading the controller / view and the directive or something.
//edit:
I guess it is not really a problem with the vs-google directive nor google itself, maybe just they way of them being initiated. Vs-google takes the element of the directive and initializes its code. Because google-API is included in the index.html file and a directive loads on state change, it seems that it reinitializes the DOM element or something, but still, the event is just called once

How to capture the closing event of an aside when clicked outside or ESC in AngularJS?

I have a case where in which 2 asides are loaded and I have to clear a variable when the aside is closed pressing ESC or by clicking outside the aside.
I searched online and found that the following code can be used in the case of a modal. What is the code for aside?
scope.$on('modal.hide', function() {
console.log('modal... -hide');
});
How to watch for an Aside closing in angular-strap
The above code is not working for aside.
Is this approach correct? Otherwise, please suggest a method.
In the above case the modal name is not specified. So when we have more than one modal or aside how do we differentiate the closing of the modal or aside? In the current case, I don't have to differentiate the modals. But how to catch the event differently?
Update
The following code woks for aside.
scope.$on('aside.hide', function() {
console.log('aside... -hide');
});
The second question of how to identify each aside closing differently needs to be found out now.
With v2.1.1 of angular-strap the hide event for $aside was changed to aside-hide.
The AngularJS framework invokes handlers of $scope/$rootScope events with arguments:
scope.$on('aside.hide', function(event, data) {
console.log('aside... -hide');
console.log(event);
console.log(data);
});
Use those arguments to get information about the event.

$uibModal TypeError: Cannot read property 'close' of undefined

I am working in ServiceNow and have a button that pulls up a modal window that renders an embedded form. When a user submits, I have the embedded form $broadcast 'closeModal', and the button receives it to close. My client script looks like this for the embedded form:
$rootScope.$broadcast('closeModal');
and on my button that brings up the modal, my client script looks like this:
$rootScope.$on('closeModal', function() {
c.modalInstance.close();
});
This actually does close the modal window, but my console is showing "TypeError: Cannot read property 'close' of undefined"
Any idea why this is showing up?
Additionally, in my screenshot above, that typeerror actually shows up twice, for two different widgets. I am broadcasting and retrieving the same event for both widgets. I'm not sure if that's against best practice, but I've tried changing one of them to 'closeModal2' for example and the same typeError still shows.
Any suggestions or advice is greatly appreciated!
-- ADDED --
This is a screenshot of my console after logging c:
Simple hack is :
$rootScope.$on('closeModal', function() {
c.modalInstance && c.modalInstance.close();
});
Another suggestion is use $rootScope.$emit and listen at specific scope level $scope.$on

ionic + android back button + sidemenu isOpen detection - not working reliably

I have an odd situation. I am writing an angular + ionic app with a left slide menu and here is what I am trying to do:
1) Trap the Android back button
2) When you tap the back button, if the menu is not open, take you to the menu (open it)
3) If the menu is open and you hit the back button, exit the app
To trap the back button, I have this code in app.run (also tried relocating to a base controller and injecting it with $controller into other controllers, did not make a difference)
What I am noticing is that if I actually tap the 'menu icon' of the menu, the "isOpen" reliably prints true/false alternately as a I open and close the menu
But, when I tap the Android back button, it works the first time (prints true or false), but every subsequent tap does not change the isOpen state, while the menu actually toggles.
This therefore makes it impossible for me to programmatically detect if the menu is open or close within the android back button handler.
It's confusing me why this is only a problem within the android back handler, and not a problem when I tap the menu item. It's the same code that is called in both cases, which is
$ionicSideMenuDelegate.toggleLeft();
My Android handler code:
$ionicPlatform.registerBackButtonAction(function (event) {
$ionicSideMenuDelegate.toggleLeft();
$ionicSideMenuDelegate.$getByHandle('sideMenu').toggleLeft();
$timeout ( function() {
console.log ("Status of SIDE MENU IS : " + $ionicSideMenuDelegate.$getByHandle('sideMenu').isOpen());
},1000);
}, 100);
I've also set up a codepen, though not sure how one can test it on and android device, because every time I try and hit the backbutton on a codepen or jsfiddle, it makes the browser go back a page.
Any insight into what is going on? I've asked in the ionic forum, but haven't been able to find out why (yet) --> hence the post to the SO community in the hopes it reaches a wider audience.
registerBackButtonAction needs a priority to override the other actions:
The priorities for the existing back button hooks are as follows:
Return to previous view = 100 Close side menu = 150 Dismiss modal =
200 Close action sheet = 300 Dismiss popup = 400 Dismiss loading
overlay = 500
Your back button action will override each of the above actions whose
priority is less than the priority you provide. For example, an action
assigned a priority of 101 will override the 'return to previous view'
action, but not any of the other actions.
I've tested this code and it works as expected:
.run(function($ionicPlatform, $ionicSideMenuDelegate, $ionicPopup) {
$ionicPlatform.registerBackButtonAction(function(e) {
e.preventDefault();
if (!$ionicSideMenuDelegate.isOpenLeft()) {
$ionicSideMenuDelegate.toggleLeft();
} else {
navigator.app.exitApp();
}
}, 1000);
});
As you can see I've used priority 1000 to make sure that I override all the default actions.
I've also used preventDefault(). I don't think you need this but, just in case.
This bit of code only works for the left-side menu as I only check:
$ionicSideMenuDelegate.isOpenLeft()
and only open the left one:
$ionicSideMenuDelegate.toggleLeft()
but you can change it to work with the right menu as well.
UPDATE:
If someone is interested to find out more about Android and Back Button this is the best article I've read so far.

AngularJS - AlertFactory open dialog behavior

i'm creating an AlertFactory because ui.bootstrap.dialog doesn't works in my app.
So i type follow code: http://jsfiddle.net/Premier/BHqKB/17/
enter code here
It works very well if you click on the "Open dialog" button: on screen appear a dialog with my messages.
I also register a listener on keydown: listener fires a broadcast event on which is registered a scope related function. This function calls openDialog to show the dialog. In this way angular doesn't interpolates arguments and alert is shown with {{title}} placeholder.
What is wrong in my code?
Thank you.
You need an $apply to invoke a digest cycle.
ng.element(document).on('keydown', function(e){
//alert('keydown');
//openDialog();
$rootScope.$broadcast('openDialog');
$rootScope.$apply();
});

Resources