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.
How can I convince the Angular 4 router to disable direct browser navigation within my app?
Angular can't do that because that's not something controlled by Angular. When you go the address bar and type in address and then press enter a browser loads a new page. It can be an Angular application or can be any other application. It's a browser functionality. Angular controls navigation only inside the app when you click on the routerLink
.
You could try to use onbeforeunload but it has its limitations.
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