Angular 4 router: prevent direct browser navigation

梦想的初衷 提交于 2019-12-12 08:44:22

问题


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 { }

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/45427632/angular-4-router-prevent-direct-browser-navigation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!