How can I convince the Angular 4 router to disable direct browser navigation within my app?
I have looked into the router hooks CanActivate
and CanDeactivate
and implemented them but CanDeactivate
does not fire at all when using direct browser navigation.
I can use CanActivate
to prevent the url but only after the app reboots, which takes time and undesired changes in the browser window.
I want to be able to catch the direct browser navigation BEFORE the app reboots.
In case this helps: I want to disallow direct browser navigation altogether, so I don't need a solution that allows certain urls and disables others.
Here's my router definition:
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent, canActivate: [RouteGuardService] },
{ path: 'users', component: UsersMainComponent, canActivate: [RouteGuardService] },
{ path: 'vendors', component: VendorMainComponent, canActivate: [RouteGuardService] },
{ path: 'invoices', component: InvoicesMainComponent, canActivate: [RouteGuardService] },
{ path: 'offers' , component: EsdMainComponent, canActivate: [RouteGuardService] },
{ path: 'settings' , component: SettingsMainComponent, canActivate: [RouteGuardService] },
// Callback MUST not be route guard protected.
{ path: 'callback' , component: CallbackComponent },
{ path: 'createvendor' , component: CreateVendorsComponent, canActivate: [RouteGuardService] },
{ path: 'customerdashboard' , component: CustomerDashboardComponent, canActivate: [RouteGuardService] },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [RouteGuardService]
})
export class AppRoutingModule { }
The following solution is not an Angular based one. As Maximus explained in his answer this is a browser issue and therefor the solution must be browser based.
This solution is derived from an answer on this site (see here) I have written a little (typescript) service with the following three methods:
private preventNavigation(): void {
const location = window.document.location;
const originalHashValue = location.hash;
window.setTimeout(() => {
location.hash = 'preventNavigation' + (9999 * Math.random());
location.hash = originalHashValue;
}, 0);
}
public disableBrowserNavigation(): void {
window.addEventListener('beforeunload', this.preventNavigation, false);
window.addEventListener('unload', this.preventNavigation, false);
}
public enableBrowserNavigation(): void {
window.removeEventListener('beforeunload', this.preventNavigation);
window.removeEventListener('unload', this.preventNavigation);
}
This works fine but I'm still open to other solutions.