15

I've implemented a CanDeactivate guard to avoid user leave the page during the upload and it works. The problem is that my message is always a default message (in dutch because of the browser language) and, even setting a message myself, still show the same default confirm window. I would like to write my own message (actually I have a modal that I want to show, but first I would like to see working just with my simple message)

Any ideas what could it be? Am I missing something?

Here's the code

Guard.

import { Injectable, ViewContainerRef } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { DialogService } from '../services';
    
export interface PendingUpload {
   canDeactivate: () => boolean | Observable<boolean>;
}
@Injectable()
export class PendingUploadGuard implements CanDeactivate<PendingUpload> {
    constructor(
        private dialogService: DialogService,
        private viewContainerRef: ViewContainerRef
    ) { }
    
    canDeactivate(component: PendingUpload): boolean | Observable<boolean> { 
        return component.canDeactivate()
           ? true
           : confirm("Test custom message");
           //dialog I want to use later
           //this.dialogService.confirm("modal title", "modal body", this.viewContainerRef);                   
     }
 }

Component

import { Component, OnInit, HostListener } from '@angular/core';

import { Observable } from 'rxjs/Observable';

import { PendingUpload } from '../../shared/validators/pending-upload.guard';

import './../../rxjs-operators';

@Component({
    selector: 'component-selector',
    templateUrl: './html',
    styleUrls: ['./css']
})
export class ScannerUploadComponent implements OnInit, PendingUpload {
    uploading: boolean = false;

    constructor() { }

    ngOnInit() {
        this.uploading = false;
    }

    @HostListener('window:beforeunload')
    canDeactivate(): Observable<boolean> | boolean {  
        return !this.uploading;
    }
}
jps
  • 20,041
  • 15
  • 75
  • 79
Elmer Dantas
  • 4,649
  • 5
  • 30
  • 36
  • Elmer found the anders to this question here: [Angular 2 - Warn user of unsaved changes before leaving page](http://stackoverflow.com/questions/35922071/angular-2-warn-user-of-unsaved-changes-before-leaving-page/) – Jasper Risseeuw Feb 13 '17 at 10:59
  • I've seen this and still gives me a default message text (in dutch) instead of my custom message....I use the specific guard from Angular docs and works but has a bug like [this](https://github.com/angular/angular/issues/10321)..I'm struggling to make this work but with no sucess until now. – Elmer Dantas Feb 13 '17 at 13:30

1 Answers1

25

Your custom message will only be shown when trying to navigate elsewhere within your Angular app (e.g., navigating from http://localhost:4200/#/test1 to http://localhost:4200/#/test2). This is because the CanDeactivate guard only activates for route changes made via the Angular router, within your Angular app.

When navigating away from your Angular app (e.g., navigating from http://localhost:4200/#/test1 to http://stackoverflow.com, refreshing the page, closing the browser window/tab, etc.), the window beforeunload event activates (due to the @HostListener('window:beforeunload') annotation) and handles the confirm dialog on its own, without the CanDeactivate guard. In this case, Chrome and Firefox display their own pending changes warning message.

You can read more about the beforeunload event and how it works here. You'll notice in the "Notes" section that it states the following:

In Firefox 4 and later the returned string is not displayed to the user. Instead, Firefox displays the string "This page is asking you to confirm that you want to leave - data you have entered may not be saved."

Chrome follows a similar pattern, explained here.

IE/Edge still seem to offer the ability to specify a custom beforeunload message. An example of this can be seen here.

Community
  • 1
  • 1
stewdebaker
  • 4,001
  • 3
  • 12
  • 10
  • Thanks for answering, Stew!! I've already had read about the beforeunload event and see that is not possible to customize message when using it. I thought that I was doing something wrong because in your answer (from the link you've posted) none of this was mention it so...I was trying to do the impossible =]. At least now I know that I was on the right path. Thanks again. – Elmer Dantas Feb 14 '17 at 07:57
  • @ElmerDantas - no problem. I've now updated my answer to the other question to state this distinction. Sorry for the confusion. – stewdebaker Feb 15 '17 at 14:55