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;
}
}
You can use the CanDeactivate guard to prevent usesr from accidentally leaving a route/page in your application for example if such page contains a text editor with unsaved changes or an unsubmitted form.
CanActivate - Decides if a route can be activated. CanActivateChild - Decides if children routes of a route can be activated. CanDeactivate - Decides if a route can be deactivated. CanLoad - Decides if a module can be loaded lazily.
The Angular CanDeactivate guard is called, whenever we navigate away from the route before the current component gets deactivated. The best use case for CanDectivate guard is the data entry component. The user may have filled the data entry and tries to leave that component without saving his work.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With