ionic framework two popups in tandem - javascript

I have an ionic app where the user taps a button, then a popup shows up and then the user taps a button in the popup and another one shows up. This works fine in the browser but when I deploy it to an android device, after the second popup closes the page freezes and I can no longer tap the main button on the page.
Here's a short but complete app demonstrating my problem.
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<!-- version 1.0.0-beta.9 -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script>
angular.module("app", ["ionic"])
.controller("controller", function ($scope, $ionicPopup, $timeout) {
var popup1;
$scope.popup1 = function () {
popup1 = $ionicPopup.show({
template: '<button ng-click="popup2()">popup2</button>',
title: 'popup1',
scope: $scope
});
}
$scope.popup2 = function () {
$ionicPopup.alert({
title: "Popup 2"
}).then(function () {
/*
$timeout(function () {
popup1.close();
});
*/
popup1.close();
});
}
});
</script>
</head>
<body ng-app="app" ng-controller="controller">
<button ng-click="popup1()">popup1</button>
</body>
</html>

The reason this isn't working is likely that the second popup is opening before the first one closes, which could be killing Ionic's knowledge that the first one exists. If you kill the first popup before the open the second one, that should solve the issue.
I see a few options:
1. Create your buttons in an Ionic way and use the onTap method
$scope.popup1 = $ionicPopup.show({
template: 'Your template here',
title: 'popup1',
scope: $scope,
buttons: [
{
text: 'Popup2',
onTap: function (e) {
$scope.popup1.close();
return $scope.popup2();
}
}
]
});
2. Close popup1 first thing in popup2()
$scope.popup2 = function () {
$scope.popup1.close();
// Open popup 2
}
3. Open popup2 in a timeout
If the above don't work, put a timeout around the code in popup2 to give Ionic the time to close the first popup.
$scope.popup2 = function () {
// Move to the bottom of the queue to let Ionic close the first popup
$timeout( function () {
// Load popup2
});
};

My solution:
$rootScope.solidAlertPromise = $q.resolve(); // make the very first alert happen immediately
//lets create a reusable function to get rid of static and local problems
window.alert = function(message) {
//chaining does the trick
$rootScope.solidAlertPromise = $rootScope.solidAlertPromise.then(
function() {
//New Popup will rise as soon as the last Popup was closed (resolved).
//but it will rise immediately after closing the last Popup - definitely!
return $ionicPopup.alert({title: 'solidAlert', content: message});
}
);
};
//Now we can call our function sequentially
alert('After max has closed this alert-popup, the next one will rise immediately!');
alert('Next one -press OK to get the nex one-');
alert('and so on');
That's just for eplanation purpose: We should have a look at the rejection-cases etc.!
$ionicPopup.alert
can be replaced with
$ionicPopup.show
I think.

Related

How to call function in ionic angularjs with local notification

I have an application that has two buttons , Add button and Schedule button ,
When i click on the add button the notification will be triggered then the notification tab will appeared .
Here is the code
Js code
app.controller('contNoti', function ($scope, $cordovaLocalNotification)
{
$scope.add = function () {
var alarmTime = new Date();
alarmTime.setMinutes(alarmTime.getMinutes() + 1);
$cordovaLocalNotification.add({
id: "1234",
date: alarmTime,
message: "This is a message",
title: "This is a title",
autoCancel: true,
sound: null
}).then(function () {
console.log("The notification has been set");
});
};
$scope.isScheduled = function () {
$cordovaLocalNotification.isScheduled("1234").then(function (isScheduled) {
alert("Notification 1234 Scheduled: " + isScheduled);
});
};
});
<ion-content ng-controller="contNoti">
<button class="button" ng-click="add()">Add notification</button>
<button class="button" ng-click="isScheduled()">Is Scheduled</button>
</ion-content>
Ok, what I need is to make the same application with the same functionality but without the buttons. I want it to be executed automatically without clicking on the buttons. Thanks
I'm not sure I understand your question, but you want to run $scope.add() no matter what, is that correct?
If so, just add $scope.add(); after the $scope.isScheduled = function () {...}; block.
I hope that's the answer you're looking for, otherwise, please provide more details.
You could trigger your methods with the events from $ionicView:
Inside your controller:
$scope.$on('$ionicView.enter', function(data) {
$scope.add();
$scope.isScheduled();
})
They will be executed once the User enter to the view.
Note: Those functions could be private(not attached to the $scope). Because they wont be used in the View.

in ionic on registering onHardwareBackButton event the back button still make page to navigate previous page

I am new to ionic. I am using onHardwareBackButton event of ionic, the event is working correct it is taking me to register function but after going to register function it is still navigating to back page.
I am showing cordova confirm dilogbox on hardwarebackbutton event function so after clicking on cancle he can navigate to back page, but now the popup is also coming and page is also navigating back same time.I have searched and tried many code like
e.preventDefault()
e.stopPropagation()
both of them are not workign
I have tried registerBackButtonAction event also but it is not getting deregister when i leave page.
I am stuck with this problem from many hours.
The code which I am using is given below..
//this is register event i have used
showalertPopup = function(){
//showing popup
}
$scope.$on '$ionicView.enter', (event, view)->
$ionicPlatform.registerBackButtonAction showalertPopup, 100
//like this i am diregistering event
$scope.$on '$ionicView.leave', (event, view)->
$ionicPlatform.offHardwareBackButton showalertPopup
in place of registerBackButtonAction i have used onHardwareBackButton
What you can do here is registerBackButtonAction with priority 100 (see docs):
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
so, basically, you're overriding the "Return to previous view" action.
You're going to need a handler to de-register when you're leaving the view:
var backbuttonRegistration = null;
$scope.$on('$ionicView.enter', function(event, viewData) {
backbuttonRegistration = $ionicPlatform.registerBackButtonAction(function(e) {
e.preventDefault();
showalertPopup();
}, 100);
});
$scope.$on('$ionicView.leave', function(event, viewData) {
if (backbuttonRegistration)
{
backbuttonRegistration();
}
});
According to the documentation, registerBackButtonAction :
Returns: A function that, when called, will deregister this
backButtonAction.
Your controller should look something like this:
.controller('homeController', function($scope, $ionicPopup, $ionicPlatform) {
function showalertPopup() {
var alertPopup = $ionicPopup.alert({
title: 'Don\'t eat that!',
template: 'It might taste good'
});
alertPopup.then(function(res) {
console.log('Thank you for not eating my delicious ice cream cone');
});
}
var backbuttonRegistration = null;
$scope.$on('$ionicView.enter', function(event, viewData) {
backbuttonRegistration = $ionicPlatform.registerBackButtonAction(function(e) {
e.preventDefault();
showalertPopup();
}, 100);
});
$scope.$on('$ionicView.leave', function(event, viewData) {
if (backbuttonRegistration)
{
backbuttonRegistration();
}
});
});
PS:
You can registerBackButtonAction with the highest priority of all - let's say 1000 - and it will work:
backbuttonRegistration = $ionicPlatform.registerBackButtonAction(function(e) {
e.preventDefault();
showalertPopup();
}, 1000);

Angular ui bootstrap modal call close function when closing from overlay

How can i run the same function when the user is closing the modal from the overlay?
For example now i have close button with this function:
close() {
this.$modalInstance.close();
this.AlertService.reset();
}
But when the user close the modal from the overlay this function does not run.
Take a look at the angular bootstrap documentation.
$modal.open returns a modal instance, with one parameter being 'result'. This is a promise triggered when the modal is dismissed.
var $modalInstance = $modal.open({ ... });
$modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
Also, note the modal.closing event which is broadcast before closing, and can be used to prevent closing with 'event.preventDefault'.

window.open + Opening content in 2 tabs

I'm using angular js and javascript in my application.And here , when I click <a> tag it call a method in angular controller ,which has $window.open();.Every time I click it content open in 2 tabs.What is the reason for that? Please help me out.
HTML
<li>Test Click</li>
Angular controller
controllers.controller('LogoutCtrl', ['$scope', '$location','$cookieStore','$rootScope','$window',
function($scope, $location,$cookieStore,$rootScope ,$window) {
$scope.test_home = function () {
$window.open('www.yahoo.com');
};
}
]);
Try using preventDefault:
$scope.test_home = function (e) {
e.preventDefault();
$window.open('www.yahoo.com');
};
Or, use return false;
Nothing in common with $window.open, maybe some other event listener is bind to #test_home or some browser plugin is responsible for it.
Short example on jsfiddle shows that method will open only one window / tab.
angular.module('windowOpen', []).controller('open', function ($scope, $window) {
$scope.openMe = function () {
$window.open('http://google.com/');
};
});
jsfiddle: http://jsfiddle.net/krzysztof_safjanowski/AKB4c/

javascript Confirm replacement with return true/false

Since jquery UI dialog does not support returning true/false, I need some other way to replace a javascript confirm.
It has to return true/false, so that my validation processes in javascript will run:
var where_to_coupon = confirm(pm_info_msg_013);
if (where_to_coupon== true) {
doSubmit=true;
return doSubmit;
The only way I know of doing that is passing a callback to the function.
The problem you face is that JQuery UI will not block the execution like confirm to wait for user input so you need to open the dialog and when the user clicks an answer act accordingly.
If you use Jquery UI dialog you can bind the callback functions to the buttons.
For instance:
myConfirm("Are you sure?", function(){ [YES CODE] }, function(){ [NO CODE] });
Your custom confirm will look like this:
var myConfirm = function(msg, yesAction, noAction){
$.dialog{
[CODE],
buttons: {
yes: yeasAction,
no: noAction
}
};
};
jQuery UI can do what you want, you simply have to adjust your code to work in an async way. Ariel Popovosky gave an answer which attempts to wrap a dialog call into a simple function call, and would work well but would require the same basic sync/async code modifications that any change from window.confirm would require.
Using window.confirm we use a synchronous way of doing things--program halts while user makes a decision. See example: http://jsfiddle.net/9jY7E/
Using UI's dialog, we simply move the behavior which should happen on confirm into the behavior assigned to one of the UI buttons. The dialog shows, and the program continues to run. But because you moved your "ok" code into the functionality bound to the button, that code doesn't run until the user clicks it. The following link is the same example I showed with window.confirm, but has been modified to use UI dialog: http://jsfiddle.net/9jY7E/1/
I don't know of any replacement for window.confirm which works just like window.confirm but allows for your own styling. All dialog systems I know of work somewhat similar to UI.
Additional: At the following link you will find a 3rd example of the same external link confirmation using the methodology Ariel gave in his answer: http://jsfiddle.net/9jY7E/2/
This is a little convoluted, but it works for me. It sets a "global" variable and tests that value to see if the dialog should be displayed.
I know it probably isn't the most efficient method.
The confirmIt funciton returns true or false.
The reason for the setTimeout("confirmItConfirmed=false;",500); near the end is to reset the variable so the next time the function is called it won't just return true.
Some browsers do better at handling the auto height and width than others.
The notice function is a replacement for alert and confirmIt replaces confirm.
<html>
<head>
<title>jQuery Confirm & Alert Replacements</title>
<link type=text/css href=http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/redmond/jquery-ui.css rel=stylesheet />
<script type=text/javascript src=https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js></script>
<script type=text/javascript src=https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js></script>
<script type=text/javascript>
var confirmItConfirmed = false;
var jq = $.noConflict();
function notice(message,title,height,width) {
if (!title)
var title = document.title+' says...';
jq('body').append('<span id=noticeDialogSpan style=display:none></span>');
jq('#noticeDialogSpan').html('<div id=noticeDialog title="'+title+'">'+message+'</div>');
if (!width)
var width = jq('#noticeDialogSpan').width()+40;
if (!height)
if (jq('#noticeDialogSpan').height() > jq(window).height()-100)
var height = jq(window).height()-100;
else
var height = 'auto';
jq('#navMenu').hide();
jq('#noticeDialog').dialog ({
height: height,
width: width,
modal: true,
close: function(event,ui) {
jq(this).dialog('destroy');
jq('#noticeDialog').remove();
jq('#noticeDialogSpan').remove();
jq('#navMenu').show();
},
buttons: {
'Close': function() { jq(this).dialog('close'); }
}
});
}
function confirmIt(e,message,title,height,width) {
if (!confirmItConfirmed) {
if (!title)
var title = document.title+' says...';
jq('body').append('<span id=confirmationDialogSpan style=display:none></span>');
jq('#confirmationDialogSpan').html('<div id=confirmationDialog title="'+title+'">'+message+'</div>');
if (!width)
var width = jq('#confirmationDialogSpan').width()+40;
if (!height)
if (jq('#confirmationDialogSpan').height() > jq(window).height()-100)
var height = jq(window).height()-100;
else
var height = 'auto';
jq('#navMenu').hide();
jq('#confirmationDialog').dialog ({
height: height,
width: width,
modal: true,
close: function(event,ui) {
jq('#confirmationDialog').remove();
jq('#confirmationDialogSpan').remove();
jq(this).dialog('destroy');
jq('#navMenu').show();
},
buttons: {
'Confirm': function() {
jq(this).dialog('close');
confirmItConfirmed = true;
e.click();
},
'Cancel': function() { jq(this).dialog('close'); }
}
});
}
setTimeout("confirmItConfirmed=false;",500);
return confirmItConfirmed;
}
function testIt(e) {
if (confirmIt(e,'Are you sure you want to continue?','My Title'))
notice('You clicked Confirm','My Title');
}
</script>
</head>
<body>
<br />
<br />
Click HERE to test a link.
<br />
<br />
Click this button to test it too <input value='Click Me' type=button onclick="testIt(this)" />
</body>
</html>
This could also be done using boopup + callbacks:
Boopup.confirm("This is a boopup confirm!", function(agree) {
console.log(agree);
})
https://github.com/petruisfan/boopup

Categories