Detect when user leaves window - angularjs

I want to detect when user exit window with AngularJS. My app doesn't use ngRoute. So, I can't use $destroy or $locationChangeStart.
Can you help me ?

You can use $locationChangeStart:
$scope.$on('$locationChangeStart', function( event ) {
var answer = confirm("Are you sure you want to leave this page?")
if (!answer) {
event.preventDefault();
}
});
Or use onbeforeunload:
window.onbeforeunload = function (event) {
var message = 'Are you sure you want to leave this page?';
if (typeof event == 'undefined') {
event = window.event;
}
if (event) {
event.returnValue = message;
}
return message;
}

Related

Execute an Angular function only if the current tab is active in the browser

I have an angular js function which should be called for every 2 seconds only when the current tab is open in the browser. Is there any way to check whether the current page is active in the browser.
$scope.callAtInterval = function() {
var url = "http://127.0.0.1/test";
$http.get(url).success( function(response) {
$scope.initial = response;
},
function errorCallback(response) {
$scope.result=response;
});
}
$interval( function(){ $scope.callAtInterval(); }, 5000);
}
I think below piece of code is self-explanatory
import { HostListener} from "#angular/core";
#HostListener("window:visibilitychange", ["$event"])
onVisibilityChange($event) {
const isVisible = $event.target.visibilityState === 'visible';
this.logger.info(isVisible);
if (isVisible) {
// tab is visible
} else {
// tab is not-visible
}
}
You would use the focus and blur events of the window:
$(window).on("blur focus", function(e) {
var prevType = $(this).data("prevType");
if (prevType != e.type) { // reduce double fire issues
switch (e.type) {
case "blur":
// cancel your interval function
break;
case "focus":
// emit your interval function
break;
}
}
$(this).data("prevType", e.type);
})

$locationChangeStart is not working in firefox

$scope.$on("$locationChangeStart", function (event, next, current) {
if (!$rootScope.isPopupOpen) {
if ($rootScope.isUrlLoad) {
window.location.reload();
}
}
$rootScope.isUrlLoad = true;
});
In other browser,i have no problem for loading..But in firefox it continuously loading.can anyone please suggest me?
Your problem it's probably related to the fact $locationChangeStart it's called even the first time your page load.
Simply get rid of this issue with a flag:
var firstTime = true;
$scope.$on("$locationChangeStart", function (event, next, current) {
if(firstTime){
firstTime = false;
event.preventDefault();
return;
}
if (!$rootScope.isPopupOpen) {
if ($rootScope.isUrlLoad) {
window.location.reload();
}
}
$rootScope.isUrlLoad = true;
});

Correct way to destroy timeout in angularjs progressbars?

I have the following code to display a progressbar:
var cancelTimeoutProcess = $timeout(function () {
if (defer !== null) {
vm.setProcessingParameters('No Message');
defer = vm.openProgressBar();
deferTimer.resolve();
}
}, 1000);
// cancel the $timeout service
$scope.$on('$destroy', function () {
if (cancelTimeoutProcess) {
$timeout.cancel(cancelTimeoutProcess);
cancelTimeoutProcess = null;
}
});
Wanted to confirm if this is the right way to launch a progressbar and destroy the timeout?

disable'$scope.$on('$locationChangeStart' )' if user click cancel?

I have problem when the user click cancel and it is true it will redirtect i it will trigger $scope.$on('$locationChangeStart') becouse of that I will have 'You have unsaved changes. If you continue your changes will be lost.' appear twice. just want to ask how can I disable'$scope.$on('$locationChangeStart' )' if user click cancel
code
$scope.cancel = function() {
var validator = npFormValidator($scope);
if ($scope.npForm.$dirty) {
var answer = confirm('You have unsaved changes. If you continue your changes will be lost.');
if (answer) {
$location.path('/home');
} else {
validator.addWatches();
event.preventDefault();
}
}
};
$scope.$on('$locationChangeStart', function (event) {
var validator = npFormValidator($scope);
if (validator.valid() && $scope.model.clickedSave) {
window.onbeforeunload = undefined;
} else {
if ($scope.npForm.$dirty) {
var answer = confirm('You have unsaved changes. If you continue your changes will be lost.');
if (!answer) {
validator.addWatches();
event.preventDefault();
}
}
}
})
;
You can set a flag and check it in your event receiver:
var canceled = false;
$scope.cancel = function() {
var validator = npFormValidator($scope);
if ($scope.npForm.$dirty) {
var answer = confirm('You have unsaved changes. If you continue your changes will be lost.');
if (answer) {
canceled = true;
$location.path('/home');
} else {
canceled = false;
validator.addWatches();
event.preventDefault();
}
}
};
$scope.$on('$locationChangeStart', function (event) {
if (canceled) return;
var validator = npFormValidator($scope);
if (validator.valid() && $scope.model.clickedSave) {
window.onbeforeunload = undefined;
} else {
if ($scope.npForm.$dirty) {
var answer = confirm('You have unsaved changes. If you continue your changes will be lost.');
if (!answer) {
validator.addWatches();
event.preventDefault();
}
}
}
});

Registering beforeunload event in directive

I have the following directive which I use to warn the user if they attempt to close the window or navigate away without saving their changes:
app.directive('dirtyTracking', ['$window', function ($window) {
return {
restrict: 'A',
link: function ($scope, $element, $attrs) {
function isDirty() {
var formObj = getProperty($scope, $element.attr('name'));
return formObj && formObj.$pristine === false;
}
//So we can read string keys such as foo.bar and correctly
//traverse the javascript object
function getProperty(obj, prop) {
var parts = prop.split('.'),
last = parts.pop(),
l = parts.length,
i = 1,
current = parts[0];
while ((obj = obj[current]) && i < l) {
current = parts[i];
i++;
}
if (obj) {
return obj[last];
}
}
function areYouSurePrompt() {
if (isDirty()) {
return 'You have unsaved changes.';
}
}
window.onbeforeunload = areYouSurePrompt;
//window.addEventListener('beforeunload', areYouSurePrompt);
$element.bind("$destroy", function () {
window.removeEventListener('beforeunload', areYouSurePrompt);
});
$scope.$on('$locationChangeStart', function (event) {
var prompt = areYouSurePrompt();
if (!event.defaultPrevented && prompt && !confirm(prompt)) {
event.preventDefault();
}
});
}
};
}]);
As it currently stands, this works, but as you can see, I have to explictly set the window.onbeforeunload property. The problem with this approach is that if I have other directives that want to do things on the save event, they will clobber each other.
When I attempted to use window.addEventListener or $window.addEventListener the event does not seem to work as expected.
Stepping through the debugger, the code does enter the areYouSurePrompt function and does return the string, however I am not prompted with a confirm dialog before the window closes.
I am aware I can use the approach where I save the current value of window.onbeforeunload but I'd rather figure out why using the addEventListner isn't working as expected.

Resources