This question already has answers here:
Close a window opened with window.open() after clicking a button
(2 answers)
Closed last year.
I created an external window in the Angular application, everything works fine but I want to close the external window after application logout
written the code below, I'm moving from 1 page to another page then the external window closing properly. If I press the logout button then the external window does not close (ngOnDestroy is not called in the case of application logout)
ngAfterViewInit() {
this.externalWindow = window.open('', '', `width=${this.wWidth},height=${this.wHeight},left=${this.wLeft},top=${this.wTop}`)
this.host = new DomPortalOutlet(
this.externalWindow.document.body,
this.componentFactoryResolver,
this.applicationRef,
this.injector
)
this.host.attach(this.portal)
}
ngOnDestroy() {
this.externalWindow.close()
}
this.externalWindow.close()
is indeed the functionality you need to use. The problem is that you need to trigger it upon logout click as well. You can have something like
onClick="closeExternalWindow()"
of course, you need to implement closeExternalWindow which does the logout for externalWindow and then call this function both on destroy and logout click.
ngOnDestroy fires only when component destroys. In the logout use case, we are redirecting to the login URL which means it refreshes the page (This is outside angular workflow) hence ngOnDestroy not firing.
If I move 1 route to a different route within the application then ngOnDestroy fires and closes the external window.
This article helped me to find the solution
ngOnDestroy not firing on page reload
Solution:
ngOnInit() {
window.onbeforeunload = () => this.ngOnDestroy()
}
Related
I have a requirement to show a prompt whenever our reservation page is navigated away from. When navigating within the app, there is no problem. A simple $onLocationChange works fine with a custom prompt. However when navigating to , for example, google or our logout page (which is in a separate angular app) the $onLocationChange does not work. In this case, I used:
window.onbeforeunload = onUnloadAppStart;
function onUnloadAppStart() {
var message = figureOutWhichMessageToUse();
return message;
}
this way I can at least customize the navigate message, even though I cant change the prompt box itself. However this causes a memory leak. So I need to set to null when I leave. Something like this:
$scope.$on("$destroy", function() {
window.onbeforeunload = null;
}
however this(the $destroy event) only seems to fire when I navigate within the app, same as the $onLocationChange. Furthermore I need to clean up binding AFTER the prompt, which is after the onUnloadAppStart function. This is because if I remove the binding and the user says "no, stay on this page", now my "onbeforeunload" is screwed up. Is there a way to fire functions after the onbeforeunload prompt?
Suppose I have 3 views (login, chat and Map) in an AngularJS application. If I'm in Map View and clicked on refresh button my page must get redirect to chat view after refreshing page. Experts please suggest how to implement.
very simple method I tried to implement.In test function I gave $rootScope.test=true; in chat view controller where as method called in Mapview. Whenever I reload my page value will get be undefined and and gave if condition with
if($rootScope.test==undefined)
{
$location.path('/chat');
}
you can implement you'r state navigation inside beforeunload browser event
var windowElement = angular.element($window);
windowElement.on('beforeunload', function (event) {
// your code for state navigation
event.preventDefault();
});
I want to trigger the window.onbeforeunload method while the user tries to refresh the browser and show a messsage to save his current work before leaving.
I am doing an angularjs application.
The below is my landing page url
http:localhost:9000/#/parentPage/
After button click user is navigated to
http:localhost:9000/#/parentPage/childPage1/:id
In childPage1Ctrl i defined the method for load
window.onbeforeunload = function(){
return "This is a message to remind you to save your experiment before leaving the page";
};
But when I launch the application the onbeforeunload method is being called.
How do i prevent this and bind the method to only that particular page?
How can i reload a particular childpage and access the id from the url?
Any help would be appreciated.
In your child contorller js destroy or Unregister the onbeforeunload event when the scope is out of this controller.
$scope.$on('$destroy', function() {
delete window.onbeforeunload;
});
I'm currently using Backbone.Marionette to create a SPA and in one of the views it is possible for the user to navigate away with unsaved changes. I can control some of these events, like buttons and menu options within the view that would take the user away, but some others would require to manipulate either Backbone.Router or work with the DOM events directly.
I already tried listening to beforeunload (doesn't work as the application is still loaded) and hashchange (doesn't work as you cannot stop the browser from navigating away). These solutions (1, 2, 3) don't work in this case, the Javascript is never unloaded.
Changing the Backbone.Router seems to be the best option, but because of how it is initialized I don't think it is possible to introduce this feature or at least I cannot find a way of doing it. This solution, for example, doesn't work because hashchange is not cancelable (you cannot call stopPropagation on it), and this other solution doesn't work because navigate is not defined on the Backbone.Router object.
Any suggestions?
I've managed to find a solution to this, although some more work is required. For this solution, I am assuming that you keep track when a view is dirty.
There are 4 main ways of moving out of a view;
Click on a link on the view
Click on link outside the view
Click on refresh or external link
Click on back/forward on the browser
1. Application link
This is the easiest case. When you click on your own link, you have to check if your view is dirty. For example, I have an in-app back button that is handled by a historyBack function. On the view:
historyBack: function() {
if (this.isDirty) {
answer = confirm("There are unsaved changes.\n\nDo you wish to continue?")
if (answer) {
this.isDirty = false
window.history.back()
}
}
else {
window.history.back()
}
}
2. Links outside your view
This type of interaction can be handled by extending the Router prototype's execute method, not the navigate method as proposed in other places.
There should be a variable somewhere accessible by the Router that stores the state of the view. In my case, I'm using the Router itself and I update this variable every time I change the dirty flag on the view.
The code should look something like this:
_.extend(Backbone.Router.prototype, {
execute: function (callback, args, name) {
if (Backbone.Router.isDirty) {
answer = confirm "There are unsaved changes.\n\nDo you wish to continue?";
if (!answer) {
return false;
}
}
Backbone.Router.isDirty = false
if (callback) callback.apply(this, args)
}
}
3. Refresh or external link
Refresh and external links actually unload your Javascript so here the solutions based on beforeunload (see question) actually work. Wherever you manage your view, I use a controller but let's assume it's on the same view, you add a listener on show and remove it on destroy:
onShow: function() {
$(window).bind("beforeunload", function (e) {
if (this.isDirty) {
return "There are unsaved changes.";
}
}
}
onDestroy: function() {
$(window).unbind("beforeunload");
}
4. Back/Forward on the browser
This is the trickiest case and the one I haven't figured out completely yet. When hitting back/forward, the user can navigate out of the app or within the app, both cases are covered by the code on 1 and 3, but there is an issue I can't figure out and I will create another question for it.
When hitting back/forward, the browser changes the address bar before calling the router so you end up with an inconsistent state: The address bar shows a different route to the application state. This is a big issue, if the user clicks again on the back button, after saving or discarding the changes, she will be taken to another route, not the previous one.
Everything else works fine, it shows a pop up asking the user if she wants to leave or continue and doesn't reload the view if the user chooses to stay.
I am writing an app that uses AngularJS and ui-router. I have a button that refreshes the page by reloading the page, and the functionality that automatically logs users out when the window or tab is closed. Now both functions work awesome (and done using traditional javascript to make things simple). See below:
<script>
// Refreshes by reloading page
function refresh() {
location.reload();
}
// Automatically logs users out when browser or tab is closed
window.onunload = function(){
localStorage.clear();
}
</script>
However, the problem is when the reload button is clicked it also logs the current user out and this is not what I want. I only want the user to be logged out when the window is closed. Is there anyway this can be done? Will reloading the route in my controller fix the problem?
Not a good solution but you can use a global flag that you can set when you are reloading the page
var refh = false;
function refresh(){
ref = true;
location.reload()
}
window.unonload = function(){
if(!refh)
localStorage.clear();
}