Chaining events in AngularJS - javascript

I'm trying to call a function after a popup automatically closes after 1 second.
This is my code:
$timeout(function() {
var closeit = myPopup.close();
closeit.then(function() {
$scope.dosomething();
});
}, 1000);
The dosomething function is never called. I'm new to AngularJS, anyone who can help me with this?

$ionicPopup - $ionicPopup.show(options) documentation:
Returns: object A promise which is resolved when the popup is closed.
Has an additional close function, which can be used to
programmatically close the popup.
var myPopup = show(options); // when you create a popup with $ionicPopup, you get a promise for the close event
myPopup.then(function() { // add a callback to the promise when it's fulfilled - ie the popup was closed
$scope.dosomething();
});
$timeout(function() {
myPopup.close();
}, 1000);

Related

Calling jQuery Dialog twice

I have 2 functions: myFunc1 and myFunc2. When myFunc1 is called, a jQuery confirmation Dialog appears. When the user clicks yes, myFunc2 is called, which should show another dialog.
But, despite successfully calling myFunc2, the second dialog never appears.
Here is a fiddle.
function myFunc1() {
dialog().then(function(data) {
if (data == "yes") {
console.log("clicked yes: show another dialog")
myFunc2();
} else {
console.log("clicked no")
}
});
}
function myFunc2() {
dialog();
console.log("myFunc2 is called")
}
function dialog(title) {
var def = $.Deferred();
$("#dialog").dialog({
modal: true,
buttons: {
"Yes": function() {
def.resolve("yes");
$(this).dialog("close");
},
"No": function() {
def.resolve("no");
$(this).dialog("close");
}
}
});
return def.promise();
}
$("button").on("click", myFunc1);
You are resolving the Deffered-Object before you are actually closing the first dialog. So when the then()-callback is hit, the dialog is still open, therefore no new one is created.
Just swap the functions and it should be working.
"Yes": function() {
$(this).dialog("close");
def.resolve("yes");
},
Example
When the Deferred is resolved, any doneCallbacks added by deferred.then() or deferred.done() are called. Callbacks are executed in the order they were added
.resolve()
You're using the same div to create all your dialogs, if you need to have more than one dialog open at once that will be an issue.
// Get a random unique number to use as the dialog id
var guid = Math.floor(Math.random() * 9999999999999) + 1;
// Clone the dialog div and give it a new name
$("#dialog").clone()[0].id = guid;
// Create the dialog with the new unique div
$("#"+guid).dialog({...});
Also,
// Make sure you remove the div after you close it
$(this).dialog("close").remove();

Custom confirm button with promise jquery

i'm trying to create a custom confirm pop up in jquery, i made a function that shows the custom alert when requested with inside a text and two buttons: ok, cancel.:
function showprompt(content){
$("#confirm").css("display","block");
$("#msg").text(content);
}
The problem is that how i can wait until the button clicked and get back the result, if ok so return true? i was thinking that i need to use promise and defer. How i can do?
I don't like to use precreated confirm buttons with plugins JQuery UI - Dialog
A promise is a great idea for this type of functionality (they're not only for async!). Let's say you have two buttons inside of #confirm are called #ok and #cancel.
This is how it would look:
function showprompt(content) {
var dfd = $.Deferred();
$('#confirm').css('display','block')
$('#msg').text(content);
$('#confirm')
//turn off any events that were bound to the buttons last
//time you called showprompt()
.off('click.prompt')
//resolve the deferred
.on('click.prompt','#ok',function() { dfd.resolve(); })
//reject the deferred
.on('click.prompt','#cancel',function() { dfd.reject(); });
//return a the deferred's promise
return dfd.promise();
}
Then you'd use it like this:
showprompt(content).then(
function() { alert('You clicked ok'); }, //promise resolved
function() { alert('You clicked cancel'); }, //promise rejected
);

Prevent duplcate ajaxLoad event calls added with a click event

I am using MVC Razor - The overall goal is to create a "print view" pop-up page.
The print view button is on the parent page, when clicked, an ajax event is fired which will populate an empty div with the contents that are to be included in the print preview:
//from the view
#Ajax.ActionLink("prntPreview", "Display", new { ID = Model.Detail.ID }, new AjaxOptions { UpdateTargetId = "modal" }, new { #class = "btnPreview" })
then, using JavasScript/jQuery I clone the contents of that newly populated div and create a new window with the contents:
//in the scripts file
$('.btnPreview').on('click', function () {
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
});
});
function PopupPrint(data) {
var mywindow = window.open('', '', 'height=500,width=800,resizable,scrollbars');
mywindow.document.write(data);
mywindow.focus();
//do some other stuff here
}
This is where I run into difficulty. The first time I click, everything is working as expected - however, if you do not navigate away from the parent page and try to use the print preview button a second time, the popup will be created twice, then three times etc. with each additional click.
I think that the problem is because each time the .btnPreview is clicked, a new $(document).ajaxStop event is being created, causing the event to fire multiple times.
I have tried to create the ajaxStop as a named function which is declared outside the scope of the click event and then clear it but this produces the same result:
var evnt = "";
$('.btnPreview').on('click', function () {
evnt =
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
evnt = "";
}, 300);
});
});
I also have other ajaxStop events initialised so don't want to completely unbind the ajaxStop event. Is it possible to get the name or something from each ajax event so that I can clear just that event or similar?
You can prevent adding additional triggers by checking with a variable outside of scope like this:
(function() {
var alreadyAdded = false;
$('.btnPreview').on('click', function() {
if (!alreadyAdded) {
$('.eventTrigger').click(function() {
console.log('printing!');
});
alreadyAdded = true;
}
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btnPreview">Add Event</button>
<button class="eventTrigger">Trigger</button>
Please note that the variable and function are encapsulated in a self-executing anonymous function and do not pollute global space.
The output of the sample can be seen in the developer console. If you remove the if-check then every click on the "Add Event" button produces an additional print statement on the "Trigger" button each time it is clicked (which is your problem). With the if, there will ever only be one event on the trigger button.
There were 2 issues which I needed to address.
The answer is to unbind the ajax event after it has checked that the request had completed and to unbind and reattach the button click trigger.
This is how I did it:
//in the scripts file
$('.btnPreview').off('click').on('click', function () {
$(document).ajaxComplete(function (e) {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
$(this).off(e);
});
});
I unbound the click event by adding .off('click') before the .on. this is what stopped it popping up multiple times.
The other issue was that anytime any ajax event completed (triggered by something else) that would also create the popup - to get around that, I added $(this).unbind(e); to the end of the code block which removed the ajaxComplete binding which was being triggered each time any ajax event completed.

protractor test before initial promises resolve

I want to test the state of the controller after initialization completes, but before promises resolve.
I have a button which is disabled (by class) until loading completes:
<button ng-class="{disabled: isLoading}">Show</button>
When the controller is initialized, an ajax call is made and when it resolves, the isLoading is set to false:
$scope.isLoading = true;
$http.get('/list')
.then(function(response) {
$scope.list = response.data;
$scope.isLoading = false;
});
When I test the button using protractor, there is no disabled class.
it('should enable the button after load completes', function() {
element(by.buttonText('Show')).getAttribute('class')
.then(function(buttonClasses) {
expect(buttonClasses).toContain('disabled');
});
});
I modified the button to have another class, just to see I'm not going bonkers:
<button ng-class="{disabled: isLoading, enabled: !isLoading}">Show</button>
and the test:
it('should show the select tables list after clicking the Change button', function() {
element(by.buttonText('Show')).getAttribute('class')
.then(function(buttonClasses) {
expect(buttonClasses).toContain('enabled');
});
});
Now the test passes.
I'm guessing that waitForAngular is part of the controller initialization process. How do I test the state of the button Before the promise resolves?
You can set browser.ignoreSynchronization = true before finding the element/class to not wait for promises in the app to resolve
it('should show the select tables list after clicking the Change button', function() {
browser.ignoreSynchronization = true;
expect(element(by.buttonText('Show')).getAttribute('class')).toContain('disabled');
browser.ignoreSynchronization = false;
});
Note you rarely need to use .then callbacks for expect, since expect handles unwraping of the promises.

stop and later persue javascript event in jquery ui modal dialog

I want to stop an event show a modal dialog and if the user presses yes persue this event. event.run() brings an error in firefox.
jQuery(element).click(function(event) {
event.preventDefault();
dialog.dialog({
buttons: {
'Ja': function() {
event.run();
},
'Nein': function() {
jQuery(this).dialog('close');
}
}
}).dialog('open');
});
Thanks to a friend and hashbrown I managed to solve this problem. An event cannot be paused and persued. If it is paused it will block the whole DOM. Try:
jQuery(link).click(function(){while(true)});
When using jQuery its possible to set additional event parameters what I did:
jQuery(element).click(function(event, show_dialog) {
var that = jQuery(this);
if(!show_dialog) {
dialog.dialog({
buttons: {
'Yes': function() {
that.trigger(event.type, [true]);
},
'No': function() {
jQuery(this).dialog('close');
}
}
}).dialog('open');
return false;
} else {
dialog.dialog('close');
return true;
}
});
First click show_dialog is undefined and modal dialog is shown. Clicking on Yes in modal dialog triggers the event.type (click) with the additional parameter true for show_dialog. http://api.jquery.com/trigger/#trigger-eventType-extraParameters
It was not possible to that.trigger(event, [true]);. I think cause events default action was prevented before.
That is because immediately after creating the popup the function returns and the event expires.
What you'll have to do is .trigger() a new event.
Note: set some sort of global variable to ignore this second event firing in your anonymous function (infinite loop problem).
Can I ask why you want to do this; what would click go off and do if you let it?
If it just fires off a different function, why not just call that function instead of attempting event.run()?

Categories