You might not need the destination URL for the next route since you can return an Observable<boolean>
to the CanDeactivate()
in the guard.
When our guard is checked we trigger our check for changes in the component and return a filtered Observable back to the guard. (Filter it for just the "true" value - otherwise we won't be able to continue the navigation to our desired route afterwards!)
When our check passes, we may navigate - if not we can't.
So we maybe want to show our user two buttons. One to skip saving and navigate (doNotSaveAndNavigate()
) and another one to save and continue his navigation (doSaveAndNavigate()
).. or any other help to guide him or her..
some.component.ts
import { Component } from '@angular/core';
// Utils
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'selector',
templateUrl: 'some.component.html'
})
export class SomeComponent {
// Utils
youMayNavigateSource = new BehaviorSubject<boolean>(false);
youMayNavigate$: Observable<boolean> = this.youMayNavigateSource.asObservable();
checkForUnsavedChanges(): void {
// Check your form/data for changes...
let hasSaved: boolean = false;
// Set the next value for our observable
this.youMayNavigateSource.next(hasSaved);
}
canDeactivate(): Observable<boolean> {
// Do some checking if we "can deactivate" the current route
this.checkForUnsavedChanges();
// Return an observable so we can change it later on and continue our navigation attempt
return this.youMayNavigate$.filter(el => el); // (!)
}
allowNavigation(): void {
// Set the next value for our observable to true
this.youMayNavigateSource.next(true);
}
doNotSaveAndNavigate(): void {
this.allowNavigation();
}
doSaveAndNavigate(): void {
// Save our data
this.doSave();
this.allowNavigation();
}
doSave(): void {
// do some fancy saving...
}
}
can-deactivate-guard.service.ts
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { SomeComponent } from './some.component';
@Injectable()
export class CanDeactivateGuard implements CanDeactivate<SomeComponent > {
canDeactivate(component: SomeComponent ) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}
(I guess you know how to setup the CanDeactivate for the Router but for the sake of completeness you'll find a usage example in the official docs)
FYI: If you rly just want to get the URL on CanDeactivate()
failure, subscribe to the router.events
and filter for the NavigationCancel
event like this:
this.router.events
.filter(event => event instanceof NavigationCancel)
.subscribe(el => console.log('Requested URL:', el.url));
you may need to import:
import { Router, NavigationCancel } from '@angular/router';
import 'rxjs/add/operator/filter';
and add the router
to your constructor:
constructor(private router: Router) { }