$locationChangeStart doesn't call but it called earlier - javascript

I would be want to call preventDefault event when someone change state.
$scope.$on('$locationChangeStart', (e) => {
if (!$window.confirm("Are you sure leave this page?")) {
e.preventDefault();
}
});
It doesn't work when i try to leave page.
It works if i use $rootScope.
When i use $rootScope.$on event.preventDefault doesn't work.
How can i fix it?
Thanks

you need to add a transition hook inside a run block:
run(function($transitions) {
$transitions.onBefore({}, function() {
function confirmDialog(msg) {
return new Promise(function(resolve, reject) {
let confirmed = window.confirm(msg);
return confirmed ? resolve(true) : reject(false);
});
}
})
});
for more info take a look at these links:
https://ui-router.github.io/guide/transitionhooks#promises
http://vancelucas.com/blog/using-window-confirm-as-a-promise/

Related

Changing modal content breaks AJAX events

I use jquery-ujs for ajax requests (data-remote="true"). My problem is, that the first request is okay, and while the second is running, it breaks. Whenever I call in the events $('#modal').empty() or $('#modal').text('') or $('#modal').html(''), no more events are going to be called.
To be clear, here's the code:
$(document).on('ajax:beforeSend', function () {
console.log('beforeSend');
$('#modal').empty().modal('show');
});
$(document).on('ajax:send', function () {
console.log('send');
});
$(document).on('ajax:success', function (e, xhr) {
console.log('success');
$('#modal').html(xhr).drags({ handle: '.modal-header' }).modal('show');
if (typeof doWork === 'function') {
doWork();
}
});
$(document).on('ajax:complete', function () {
console.log('complete');
});
And the console output:
beforeSend
send
success
complete
beforeSend
If I move $('#modal').empty().modal('show'); to the send event, then it is going to be called, but the success method is never called anymore (neither error neither complete, nothing more).
This problem annoys me for more hours now... Thank you for your help.
How about to move empty() to the ajax:complete?
In this case, when your modal closes, it opens empty for the next use and is ready for reuse.
I suggest that you put this command in the last step so that it does not cause any problems. Like the following:
$(document).on('ajax:complete', function () { console.log('complete'); . . . . $('#modal').empty(); });
I believe that this is not the best solution and there are definitely other solutions. But I hope this solution will solve your problem.
$('#modal').on('hidden.bs.modal', function () {
$(this).empty()
})
My workaround was to avoid using jquery-ujs events and using global ajax events, so my final working code is:
$(document).ajaxSend(function () {
$('#modal').empty().modal('show');
});
$(document).ajaxSuccess(function (e, xhr) {
$('#modal').html(xhr.responseText).drags({ handle: '.modal-header' }).modal('show');
if (typeof doWork === 'function') {
doWork();
}
});

Handling multithreadiing issue in javascript/jquery?

$(".getDetails").click(function() {
// some stuff like fetching response from server
})
when user clicks getDetails button on UI multiple times within fraction of second , jquery generates two calls for click function and my logic fails.
I think solution to this will be to disable the button on first click itself(so that use can't click multiple times). Once i get the response or just before returning
from click method i make it enable. Is there any better solution ?
If no, how can i make button disable as soon as user click button first time. I think it needs to be done before calling click method or some where in html element ?
Java provides synchronized keyword so that only one thread enters at time inside method , i am not sure is similar thing exist in javascript or not ?
Assuming the click handler executes an AJAX request you can set the button as disabled before making the request, then enable it again once the request completes. Try this:
$(".getDetails").click(function(){}
var $btn = $(this).prop('disabled', true);
$.ajax({
url: '/foo'
success: function() {
console.log('It worked!');
},
error: function() {
console.log('It failed!');
},
complete: function() {
$btn.prop('disabled', false);
}
});
});
you can try unbinding click event and after ajax call again bind click to that class
$(".getDetails").click(function(){}
$(".getDetails").unbind('click');
// some stuff like fetching response from server
)
You can use simple flag to prevent firing your logic multiple times:
var flag = true
$(".getDetails").click(function() {
if (flag) {
flag = false;
//your logic...
//when your code ends (in after-AJAX callback for example)
flag = true;
}
});
$(".getDetails").click(function(e){
var $target = $(e.currentTarget);
// assuming the click listener is on the button
$target.prop('disabled',true);
// request, stuff...and when done:
$target.prop('disabled',false);
})
try Prevent Default and return false to avoid any other event propagation
This is solution is like semaphore or monitor
var progress = false;
$(".getDetails").on('click', function(e) {
if(!progress){
progress = true;
// some stuff like fetching response from server
//also after sucessfull fetch make true to false again
}else{
console.log('something in progress');
}
e.preventDefault();
return false;
})
This should make sure that your button will not fire the async request twice, until you have a response.
function doAjaxReq() {
/*
Add your ajax operation here
as a return value of doAjaxReq
like so:
return $.ajax({
url: '/foo',
type: 'POST',
data: data
})
Since i can't use ajax here let's smilulate
it useing a promise.
*/
promise = new Promise(function(res, rej) {
setTimeout(function(){
res({foo: "bar"});
}, 1000)
})
return promise;
}
/*
Inside here you add the click handlder
only once use `elem.one('click'...`
*/
function addClickHandler(elem) {
elem.one('click', function() {
// do your ajax request and when its
// done run `addClickHanlder` again
// i'm using `.then` because of the promise,
// you should be using `.done`.
doAjaxReq().then(function(data) {
console.log(data);
addClickHandler(elem);
});
})
}
addClickHandler($(".getDetails"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="getDetails">Get Details</button>

return from parent function after click

I looked all around, but couldn't find any help with this problem.
So I have this if that is calling a function. In that I am waiting for a button press to happen. The button, therefore, should return true or false, but it's only returning to its anon-function running inside the click event and I don't know how to return from its parent function.
if ( saveConfirm() ) {
saveFunction()
}
function saveConfirm () {
$('#confirm').click(function() {
$('modal').modal('hide')
return true
})
$('#abort').click(function() {
$('modal').modal('hide')
return false
})
}
Hope you guys understand what i mean and maybe someone can help me with how to return from the call to the if through the button that is pressed.
Click handlers execute asynchronously, you should move saveFunction call to confirm click handler. There is no way for saveConfirm return boolean value you are trying to return in click handler.
$('#confirm').click(function() {
$('modal').modal('hide');
saveFunction();
})
$('#abort').click(function() {
$('modal').modal('hide');
})
You bind events in saveConfirm(). Try code below
$('#confirm').click(function() {
$('modal').modal('hide');
saveFunction();
})
$('#abort').click(function() {
$('modal').modal('hide');
})

How to check if an element is not clickable with Protractor?

It's trivial to test if an element is clickable with Protractor, but I'm stuck scratching my head trying to figure out how to check if an element is not clickable.
I've attempted to wrap the click function in a try/catch so that when an error is thrown when trying to click it should catch it and let the test pass; however, this does not work.
Here is my code for the method that does the check:
return this.shouldSeeDisabledFunds()
.then(function() {
var clickable = true;
try {
fundsElem.first().click();
} catch (e) {
clickable = false;
console.log(clickable);
} finally {
console.log(clickable);
}
console.log(clickable);
// All the way through, clickable is still true, and the console log in the
// catch is not called. I believe this is because click is asynchronous.
})
;
I have found a solution that works for this. As click() returns a promise you can simply .then off of it and throw in the successful click handler and override the catch handler to do nothing which makes the test pass if the element is not clickable.
return this.shouldSeeDisabledFunds()
.then(function() {
fundsElem.first().click()
.then(
function() {
throw "Can click Funds element that should be disabled";
},
function() {}
)
;
})
;
Maybe not applicable in your case, but a better way to check if an element is clickable is checking if it is both visible and enabled: elem.isDisplayed() and elem.isEnabled(). This way you don't accidentally click on buttons when you're not supposed to.
Fyi, there will be a library coming to help with cases like this: https://github.com/angular/protractor/pull/1703
There are actually two methods to check it.
1) Using ExpectedConditions
var EC = protractor.ExpectedConditions;
// Waits for the element with id 'abc' to not be clickable.
browser.wait(EC.not(EC.elementToBeClickable($('#abc'))), 5000);
If found to be clickable, it will return error.
2) Using protractor's isEnabled, isDisplayed and isPresent
So as far as my understanding goes, you can create isNotClickable, which will return false only if element is present, displayed or enabled and true otherwise:
function isNotClickable(element) {
return element.isPresent().then((isPresent) => {
if (isPresent) {
return element.isDisplayed().then((isDisplayed) => {
if (isDisplayed) {
return !element.isEnabled();
}
return true;
});
}
return true;
});
}
To verify Clickable : element.isDisplayed().toBe(true)
Not Clickable : element.isDisplayed().toBe(false)
Worked for me.

jQuery bind function doesn't work

I seem to have problem with jQuery bind() and unbind() functions. They seem to not get executed at all. Here's the code I have so far:
$(function() {
var init = function() {
$.get('test.php', function(j) {
if(j.r && j.r == 'error') {
console.log("1");
$('#far').bind('click', function() {
console.log("2"); return false;
});
} else {
//getData();
}
})
}();
var getData = function() {
$('#far').unbind('click', false);
};
$('#far').click(function() { ... });
});
Console only shows me 1 and no errors. I have no idea what I'm doing wrong since there are no errors and jQuery docs and StackOverflow has given me the same answer. I'm using jQuery 1.4.4
What am I doing wrong?
By calling your getData() function at the end of the $.get() function you are unbinding the event as soon as you bind it. Try commenting out the getData() call in the $.get() function and see if that helps.
As I see you're binding event before it's created, so use live instead.

Categories

Resources