5

How can we prevent closing a browser tab or the browser window itself in Angular 5.x?

I tried the solution recommended in another post (Prevent closing browser tab when form is dirty in Angular 2). Unfortunately, it's not working in Angular 5.x.

The solution below is partially working:

@HostListener('window:beforeunload', ['$event'])
handleClose(event) {
    event.returnValue = false;

What the above code does is that it displays a pop-up asking 'Do you want to leave this site?' with two buttons - Leave, Stay.

I tried the 'unload' and 'close' events instead of the 'beforeunload' also.

Advance thanks!

Narasimman V
  • 107
  • 1
  • 1
  • 6
  • 1
    Referencing http://www.w3.org/TR/html5/browsers.html#unloading-documents, I don't think it is possible to completely prevent the user from closing the document. You can only prompt a confirmation window and let the user agent decide wether to close the window. This makes sense, since it would carry a huge potential for user exploitation, if you were able to stop the user from closing a window. – Markai Feb 21 '18 at 06:46
  • Yes. I guess this may lead to some issues. Thanks for the response. – Narasimman V Feb 23 '18 at 08:41

2 Answers2

5

Maybe there's an Angular 5 problem or change I'm not aware of, but you're missing the '$' sign in the function that handles the event. Should be like this:

@HostListener('window:beforeunload', ['$event'])
handleClose($event) {
    $event.returnValue = false;
}

Edit: I can't comment, so that's why I've written this as a answer.

jufracaqui
  • 234
  • 4
  • 15
4

It is possible using both RouteGuard and pure Javascript code.

Component:

profileForm = this.fb.group({
  ClientName: ['', [Validators.required]]
});

@HostListener('window:beforeunload', ['$event']) beforeUnloadHander(event: any) {
     // alert();
     debugger
     var isFormDirty = document.getElementById('profileformStatus').innerText;
     console.log(isFormDirty);
     if(isFormDirty == 'true'){
       return false;
     }
     else{
       return true;
     }
   }

Component HTML:

<div id="profileformStatus">{{profileForm.dirty ? true:false}}</div>

Your Component Guard Service File(Optional):

import { CanDeactivate } from "@angular/router";
import { Injectable } from "@angular/core";
import { YourComponent } from "./projects/your-component";
@Injectable()

export class YourComponentCanDeactivateGuardService
    implements CanDeactivate<YourComponent> {

    canDeactivate(component: YourComponent): boolean {
        if (component.profileForm.dirty) {
            return confirm('Are you sure you want to discard your changes?');
        }
        return true;
    }
}

Your Module: add The Above Guard(Optional)

@NgModule({
    providers: [YourComponentCanDeactivateGuardService]
})

Finally

Update your routing module(Optional):

const routes: Routes = [
    {
        path: 'detail/:id',
        component: YourComponent,
        canDeactivate: [YourComponentCanDeactivateGuardService]
    }
];

Done. Now it will prevent reload/back navigation both.

Bimal Das
  • 1,882
  • 5
  • 28
  • 53