0

I've seen many articles but don't seem to find an answer when I try to close the parent window childWindow doesn't get closed. So I have these two events so far


@HostListener('window:beforeunload', ['$event'])
    beforeUnload(e:any){
        if(this.childWindow && !this.childWindow.closed){
            e.preventDefault();
            e.returnValue = false;
            
        }           
    }

    @HostListener('window:unload', ['$event'])
    onUnload(e:any){
        if(this.childWindow && !this.childWindow.closed){           
            this.childWindow.close();
        }           
    }

This code blocks are working fine but when I close the last parent window, the connected child window doesn't get closed.

note scenario: When I debug the unload event line by line, the child window is getting closed but not when I click continue probable reason: the parent window's by the time time unload is triggered, it doesn't care about the child window

Am I doing something wrong or is there any other event that I could use?

  • https://stackoverflow.com/questions/26324954/close-all-child-windows-when-parent-window-is-closed check this – Rashid88 Jan 24 '23 at 03:55
  • @Rashid88, have seen and tried it already, still child window doesn't close, My above code is working if we debug line by line(able to close the child window). but when we don't debug, it does not close the child window. Is there a way to capture what user has clicked (leave or cancel) on browser default dialog in before unload? – Ravirala Aman Jan 24 '23 at 05:54

1 Answers1

0

One way to handle this would be to give the child window some time to close before the parent window is closed. You can use the setTimeout function to delay the closing of the parent window for a short period of time, such as 100ms. This would give the childWindow.close() method enough time to execute and close the child window before the parent window is closed.

@HostListener('window:beforeunload', ['$event'])
beforeUnload(e: any) {
    if (this.childWindow && !this.childWindow.closed) {
        e.preventDefault();
        e.returnValue = false;
        setTimeout(() => {
            this.childWindow.close();
        }, 100);
    }
}

As for capturing the user action on the browser's default dialog, it's not possible to capture whether the user has clicked 'Leave' or 'Cancel' as the browser's default dialog does not provide any way to capture the user's choice.

You could try to use e.returnValue to provide your own message on the browser's default dialog and then you could set a flag based on the user's choice, but it will be different across the browsers.

@HostListener('window:beforeunload', ['$event'])
beforeUnload(e: any) {
    if (this.childWindow && !this.childWindow.closed) {
        e.returnValue = 'Are you sure you want to close the window?';
    }
}

You can also try to use localStorage or sessionStorage to store a flag indicating if the user has confirmed to close the window, but this will only work if the user does not clear the browser's storage.

If it is closing the child window, even when user has clicked cancel on dialog

One way to address this would be to use the localStorage or sessionStorage to store a flag indicating whether the user has confirmed that they want to close the window.

You can set this flag to true when the user confirms that they want to close the window, and then check the flag's value in the beforeunload event handler. If the flag is true, you can proceed with closing the child window, otherwise, you can cancel the close operation.

@HostListener('window:beforeunload', ['$event'])
beforeUnload(e: any) {
    if (this.childWindow && !this.childWindow.closed) {
        if (localStorage.getItem('closeConfirmed') === 'true') {
            this.childWindow.close();
        } else {
            e.preventDefault();
            e.returnValue = 'Are you sure you want to close the window?';
        }
    }
}

// Set the flag when the user confirms they want to close the window
confirmClose() {
    localStorage.setItem('closeConfirmed', 'true');
    window.close();
}

And you can add a confirm button on your dialog that calls the confirmClose method.

closing windows programmatically may be blocked by some browser so to be on a safer side provide a way for the user to close the window manually.

Rashid88
  • 34
  • 5
  • it's working, but it's closing the child window, even when user has clicked cancel on dialog – Ravirala Aman Jan 24 '23 at 08:56
  • I'm adding edits to the answer please check – Rashid88 Jan 24 '23 at 09:14
  • Sorry correct me if i'm wrong, if we can't even access the existing (leave and cancel) buttons. how can we add our own button on the default dialog? if yes, could you provide a solution? StackBlitz: https://stackblitz.com/edit/angular-ivy-b5kscv?file=src/app/app.component.html Reproduction: here open the childwindow and close the parent window, we'll still see the child window – Ravirala Aman Jan 24 '23 at 09:31
  • use the 'e.returnValue' property as I mentioned previously, to customize the message displayed on the dialog, and give user's a more clear understanding of what they are doing. also you can use a custom modal or dialog in your application that appears when the 'beforeunload' event is triggered, and give users the option to confirm or cancel the close operation. This modal or dialog can have custom "Leave" and "Cancel" buttons. – Rashid88 Jan 24 '23 at 09:40
  • I've seen many articles that said, we can't add a custom modal in beforeunload and neither we can show a customized message in default modal dialog in modern browsers because of security issues References: 1. https://stackoverflow.com/questions/38879742/is-it-possible-to-display-a-custom-message-in-the-beforeunload-popup 2. https://stackoverflow.com/questions/19263277/open-a-custom-popup-on-browser-window-tab-close – Ravirala Aman Jan 24 '23 at 09:55