Angular2 conditional routing

不羁岁月 提交于 2019-11-27 09:01:12
Günter Zöchbauer

update

In the new router guards can be used instead https://angular.io/guide/router#milestone-5-route-guards

original (for the long gone router)

Implement the CanActivate lifecycle hook like shown here Life cycle hooks in Angular2 router and return false if you want to prevent the navigation. See also https://angular.io/docs/ts/latest/api/router/CanActivate-var.html

As mentioned, Angular Route Guards are a good way to implement conditional routes. Since the Angular Tutorial is a bit wordy on the topic, here is a short summary how to use them with an example.

1. There are several types of guards. If you need something of the logic if (loggedIn) {go to "/dashboard"} else { go to "/login"}, then what you are looking for is the CanActivate-Guard. CanActivate can be read as "The new route X can be activated if all of the conditions Y are satisfied". You can also define side-effects like redirects. If this doesn't fit your logic, checkout the Angular Tutorial page to see the other guard types.

2. Create an auth-guard.service.ts.

3. Populate the auth-guard.service.ts with the following code:

import { Injectable } from '@angular/core';
import {CanActivate, Router, RouterStateSnapshot, ActivatedRouteSnapshot} from '@angular/router';

@Injectable()
export class AuthGuardService implements CanActivate {

  constructor(
    private router: Router
  ) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    const isLoggedIn = false; // ... your login logic here
    if (isLoggedIn) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }

}

4. Register the auth-guard.service.ts in your route-module. Also, add the key-value pair canActivate:[AuthGuardService] to all routes you want to guard. It should look somewhat like this:

const appRoutes: Routes = [
  { path: '', component: LandingComponent},
  { path: 'login', component: LoginComponent},
  { path: 'signup', component: SignUpComponent},
  { path: 'home', component: HomeComponent, canActivate: [AuthGuardService]},
  { path: 'admin', component: AdminComponent, canActivate: [AuthGuardService]},
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ],
  providers: [
    AuthGuardService
  ]
})
export class AppRoutingModule { }

That should get you started.

Here's a minimalistic demo: https://stackblitz.com/edit/angular-conditional-routing

In case if you need to render a specific component rather then redirect to it, you can do something like that:

const appRoutes: Routes = [
  {
    path: '' ,
    component: (() => {
      return SessionService.isAnonymous() ? LoginComponent : DashboardComponent;
    })()
  } 
]

I used this example for landing page, where user that was not previously logged in would either see the landing page or dashboard dashboard.

Update This code will work in dev environment but it will not build and you will get this error:

ERROR in Error during template compile of 'AppRoutingModule' Function expressions are not supported in decorators in 'ɵ0' 'ɵ0' contains the error at src/app/app.routing-module.ts(14,25) Consider changing the function expression into an exported function.

In order to fix it I created a separate module that looks as following

import {LandingPageComponent} from '../landing-page/landing-page.component';
import {DashboardComponent} from "../dashboard/dashboard.component";
import {SessionService} from "../core/services/session.service";

const exportedComponent = SessionService.isAnonymous() ? LandingPageComponent : DashboardComponent;

export default exportedComponent;

and then you just need to import module provided by that "factory"

import LandingPageComponent from './factories/landing-factory.component';
const appRoutes: Routes = [
  {
    path: '' ,
    component: LandingPageComponent
  },
]
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!