How to Redirect to a certain route based on condition in Angular 2.
Asked Answered
F

5

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.

Ferrin answered 2/12, 2016 at 13:43 Comment(2)
Use a guard maybe ?Engle
Why not make the redirction directly on your LoginComponent?Postmaster
W
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

Willful answered 8/6, 2017 at 7:11 Comment(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 elseConfab
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.Willful
Could you, please, let me know what should be returned from the canActivate?Haws
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>).Jacaranda
S
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',
  }
Stanleystanly answered 19/6, 2018 at 5:18 Comment(4)
This will break when user logs in/out after module has been initialisedBroadnax
this is the perfect answer, because it easily solve the problemGreasepaint
What about asynchrony? and what if I just change localstorage roleId to admin even if I am a user?Goofball
this is during loading. and we need that condition check during running.Diminutive
P
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
  },
  ...
}
Possessed answered 21/11, 2023 at 8:46 Comment(0)
E
0

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

Everlasting answered 17/9, 2023 at 5:16 Comment(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.Myrlmyrle
H
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
  }
];
Huygens answered 26/1 at 18:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.