35

I am creating one angular2-meteor app.

export const routes: Route[] = [{
    path: '',
    redirectTo: "login",
    pathMatch: "full"
}, 
{
    path: 'login',
    component: LoginComponent
}, 
{
    path: 'csvtemplate',
    component: TemplateComponent,
    canActivate: ['canActivateForLoggedIn'],
    children: [{
        path: '',
        redirectTo: 'dashboard' <----how to add condition for multiple path
    }, 
    {
        path:'dashboard',
        component: DashboardComponent
    },
    {
        path: 'csvtimeline/:month/:year',
        component: CsvTimelineComponent
    }, {
        path: 'csvjson',
        component: CsvJsonComponent
    }]
}];

When i login to my app using LoginComponent it will go to TemplateComponent which have three child components

  • dashboard
  • csvtimeline
  • csvjson

Now i have by default set redirectTo to my dashboard component. but in place of this redirect i want to redirect to csvjson component or csvtimeline component based on login user profile.

Suppose

If Login User is "Admin" he should be redirectTo - > dashboard Component

If Login User is "Guest" then he should be redirectTo - > csvjson component

i know we can do this in ngOnInit() of dashboard component for redirect.

if (this.user && this.user.profile.role == 'Guest') {
             this._router.navigate(['csvtemplate/csvjson']);
        }

but i am looking for better option so i don't have to open dashboard component each time and it will directly go to csvjson component.

2
  • 2
    Use a guard maybe ?
    – maxime1992
    Commented Dec 2, 2016 at 13:45
  • 2
    Why not make the redirction directly on your LoginComponent?
    – LoïcR
    Commented Dec 2, 2016 at 13:45

5 Answers 5

28

Here is the better solution: Guard the admin feature according to Angular guide.
Using CanActivate hook Steps:

1) Add auth-guard.service.ts file

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

@Injectable()
export class AuthGuard implements CanActivate {
    canActivate() {
        //Your redirect logic/condition. I use this.

        if (this.user && this.user.profile.role == 'Guest') {
         this.router.navigate(['dashboard']);
        }
        console.log('AuthGuard#canActivate called');
        return true;
    }
    //Constructor 
    constructor(private router: Router) { }
}

2) Update the routing file, in my case it's app.module.ts

import { AuthGuard } from './auth-guard.service';
import { AdminComponent } from './admin/admin.component';
@NgModule({
  declarations: [
    AppComponent,
    AdminComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,

    RouterModule.forRoot([
        {
          path: 'admin',
          component: AdminComponent,
          canActivate:[AuthGuard]
        },
        {
        path: '',
        redirectTo: '/dashboard',
        pathMatch: 'full'
       }
    ])
  ],
  providers: [AuthGuard],
  bootstrap: [AppComponent]
})
export class AppModule { }

**Reference ** https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard

4
  • Good solution, but not exact, in this case too if user knows the url of prohibited route lets say csvtimeline than he is able to go there by simply adding url in browser. this logic just redirect to router based on login condition nothing else Commented Jul 20, 2017 at 6:10
  • What if you define the prohibited path in RouterModule and set its caActivate property like this .. RouterModule.forRoot([ { path: 'csvtimeline', component: AdminComponent, canActivate:[AuthGuard] }, .....every time a user redirect to csvtimeline, the canActivate function will be called and there u have written a condition and u can redirect the user to any page you want. Commented Jul 29, 2017 at 4:06
  • Could you, please, let me know what should be returned from the canActivate? Commented May 20, 2020 at 19:55
  • Note: It is not considered good practice to navigate inside a route guard. If you want to redirect somewhere else you should instead return a UrlTree (or Promise<UrlTree>|Observable<UrlTree>).
    – Wilt
    Commented Apr 12, 2023 at 18:22
4

In routing module, u need to create local variable "route",check condition and assign requires routing path the variable and assign variable to redirectTo in routing

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

var route: string = "user";
const role = JSON.parse(localStorage.getItem("currentUser")).roleId;

if (role == "1") {
//superadmin role
 route = "project"
} else {
  //normal user role
  route = "user"
}
const adminRoutes: Routes = [ {
path: '',
component: AdminComponent,
canActivate: [AuthGuard],
children: [

  { path: '', redirectTo: route },
  {
    path: 'project',
    loadChildren: './project-dashboard/project-dashboard.module#ProjectModule'
  }, {
    path: 'user',
    loadChildren: './user/user.module#UserModule',
  }
4
  • 4
    This will break when user logs in/out after module has been initialised Commented Apr 19, 2019 at 8:29
  • this is the perfect answer, because it easily solve the problem
    – Wiki
    Commented Oct 17, 2019 at 11:29
  • 3
    What about asynchrony? and what if I just change localstorage roleId to admin even if I am a user?
    – Rip3rs
    Commented Nov 22, 2019 at 17:46
  • this is during loading. and we need that condition check during running.
    – irakli2692
    Commented Sep 1, 2022 at 9:50
1

You could also use resolvers combined with an "dummy" component:

const SwitchResolver: ResolveFn<any> =
  (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
    const user = inject(UserService).getUser();
    const router = inject(Router);
    if (user && user.profile.role == 'Guest') {
      router.navigate(['csvtemplate/csvjson']);
    }

    return of(null);
  };

@Directive()
class EmptyComponent {
}

const routes: Routes = [
  {
    path: '',
    resolve: { switch: SwitchResolver },
    component: EmptyComponent
  },
  ...
}
0

@Rip3rs jwt tokens are used for that only. you can logout your user if change is made in role from "user" to "admin"

1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Sep 19, 2023 at 9:00
0

Angular now recommands to use functional guards and flagged CanActivate as deprecated. Considering this, an easy way to answer the question is to do the following :

const rootGuard = () => {
  const router = inject(Router)
  if (inject(AuthServiceService).isAuthenticated()) {
    router.navigate(['welcome']); // Default URL when logged
  } else {
    router.navigate(['login']); // Default URL when not logged
  }
}

const appRoutes: Routes = [
  {
    path: '', component: AppComponent, canActivate: [rootGuard] // Any component would do
    // More path
  }
];

Not the answer you're looking for? Browse other questions tagged or ask your own question.