Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect empty path to login page (Angular 4)

i want to redirect from the empty path " " to my login page, when user is not logedd in. So i'm using guards and children routes to do this. However, my code is fine to all routes except " ".

This is my guard (canValidate function)

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):boolean {
   return this.canMethod();
  }

  canMethod () {
    if (Environment.ActivateGuard) {
      let token = this._auth.getCookie(AuthorizationEnum.cookieName);
      if(token) { // token exists
        let data = {
          token: token,
          module: this.module
        };

        this._auth.validate(data, AuthorizationEnum.Bearer).subscribe(
          data => { // valid token
            if ( data.res == AuthorizationEnum.emptyResponse)  { // invalid user, it doesn't belongs to this module.
              this.letsRedirect();
            } 
            else {
              let user_role = data.det[1]; // this is the user's role!.
            }
          },
          error => { //  other error
            this.letsRedirect();
          }
        );
        return true;
      } 
      else { // user don't have token
        this.letsRedirect();
      }      
    } 
    else {
      return true;
    }    
  }


  letsRedirect(){
     window.location.href = Environment.authAppUrl + AuthorizationEnum.redirectQuery + encodeURIComponent(this.url);
  }

And this is my app-routing.module.ts(only the array of routes)

const routes: Routes = [

  // TODO: Validar esta ruta
  //{ path: '', component: LoginComponent, pathMatch: 'full' },

  //Con header
  { 
    path: '', 
    children: [
      { path: '', component: HomeComponent,canActivate:[AuthorizatedGuard]},
      { path: 'inicio', component: HomeComponent, canActivate:[AuthorizatedGuard] },  
      { path: 'categorias', redirectTo: 'base-lista/categorias'},
      { path: 'videos', redirectTo: 'base-lista/videos'},
      { path: 'base-lista/:idList', component: BaseListComponent, canActivate:[AuthorizatedGuard] },
      { path: 'base-lista/categorias/gestionar-categorias', component: CategoryVideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/categorias/ver-detalles-categoria', component: ViewDetailsCategoryComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/gestionar-videos', component: VideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/ver-detalles-video', component: ViewDetailsVideoComponent, canActivate:[AuthorizatedGuard]  },
     ],
    component: AppLayoutComponent,
    canActivate: [AuthorizatedGuard],
  },

  //sin header
  {
    path: '',
    component: LoginComponent,
    children: [
      {
        path: 'login',
        component: LoginComponent
      }

    ]
  }

];

When we try to access "htpp://localhost:4200/", Angular will evaluate the route paths. The first part of the path for the first route configured is "", so let’s continue evaluating the second part which is also "", so we have a match! But the guard still need to verify if the user can access the HomeLayoutComponent (if user is logged in). If the user is logged in, then the access is granted and the user will see the HomeLayoutComponent (the navbar along with the HomeComponent being rendered in the router-outlet), otherwise it is redirected to "htpp://localhost:4200/login".

So suppose we are trying to access "htpp://localhost:4200/login". Angular will evaluate the route path again. The first part of the path for the first route configured is "", so let’s continue evaluating the second part which is "login", so we do not have a match with. We need to evaluate the next route configured. Let’s go again! The first part of the path for the first route configured is "" (this time), so let’s continue evaluating the second part which is "login" and we have a match . In this case the LoginLayoutComponent is displayed. Since there is only a router-outlet in the HTML template, only the LoginComponent will be displayed.

I am using this link to create the routing

So.. what is wrong with my code?

like image 922
Mvram Avatar asked Sep 18 '18 20:09

Mvram


3 Answers

This work for me

[
  {
    path: '',
    pathMatch: 'full',
    redirectTo: 'teams'
  },
  {
    path: 'teams',
    component: TeamsComponent
  }
]

Reference - http://vsavkin.tumblr.com/post/146722301646/angular-router-empty-paths-componentless-routes

like image 142
San Jaisy Avatar answered Sep 30 '22 01:09

San Jaisy


I managed to solve my problem, including the empty route without the guard redirecting to the login page, so that if the person is not logged in he will redirect him to login otherwise, he will enter the following definition always ensuring that the person already this logged in the system.

const routes: Routes = [

  // Sin header
  { path: '', component: LoginComponent, pathMatch: 'full' },

  //Con header
  { 
    path: '', 
    children: [
      { path: '', component: HomeComponent,canActivate:[AuthorizatedGuard]},
      { path: 'inicio', component: HomeComponent, canActivate:[AuthorizatedGuard] },  
      { path: 'categorias', redirectTo: 'base-lista/categorias'},
      { path: 'videos', redirectTo: 'base-lista/videos'},
      { path: 'base-lista/:idList', component: BaseListComponent, canActivate:[AuthorizatedGuard] },
      { path: 'base-lista/categorias/gestionar-categorias', component: CategoryVideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/categorias/ver-detalles-categoria', component: ViewDetailsCategoryComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/gestionar-videos', component: VideoComponent, canActivate:[AuthorizatedGuard]  },
      { path: 'base-lista/videos/ver-detalles-video', component: ViewDetailsVideoComponent, canActivate:[AuthorizatedGuard]  },
     ],
    component: AppLayoutComponent,
    canActivate: [AuthorizatedGuard],
  },



];

ps: sorry for my english

like image 23
Mvram Avatar answered Oct 04 '22 01:10

Mvram


Have you tried removing the '' path from your LoginComponent? It seems redundant. Unless you are using a separate layout in which case you need to specify the layout component your are using (like your AppLayoutCompnent) and not the LoginComponent twice.

change

  {
    path: '',
    component: LoginComponent,
    children: [
      {
        path: 'login',
        component: LoginComponent
      }

    ]
  }

to just

 {
    path: 'login',
    component: LoginComponent
  }

OR

  {
    path: '',
    component: LoginLayoutComponent, // <---
    children: [
      {
        path: 'login',
        component: LoginComponent
      }
    ]
  }

Another thing you should look at is using the router to handle the redirect instead of window.location. It's the "Angular" way to handle it. Inject Router into your guard and use it to navigate.

letsRedirect(){
     this.router.navigate(['/login'], { queryParams: { redirectUrl: this.url } });
  }

Finally, you can simplify the routes by using CanActivateChild. It will perform the check for all child routes instead of adding the guard to each.

  { 
    path: '', 
    children: [
      { path: '', component: HomeComponent,
      { path: 'inicio', component: HomeComponent },  
      { path: 'categorias', redirectTo: 'base-lista/categorias'},
      { path: 'videos', redirectTo: 'base-lista/videos'},
      { path: 'base-lista/:idList', component: BaseListComponent },
      { path: 'base-lista/categorias/gestionar-categorias', component: CategoryVideoComponent },
      { path: 'base-lista/categorias/ver-detalles-categoria', component: ViewDetailsCategoryComponent },
      { path: 'base-lista/videos/gestionar-videos', component: VideoComponent },
      { path: 'base-lista/videos/ver-detalles-video', component: ViewDetailsVideoComponent },
     ],
    component: AppLayoutComponent,
    canActivateChild: [AuthorizatedGuard],
  },

and update your guard to

canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):boolean
like image 35
Todd Skelton Avatar answered Sep 30 '22 01:09

Todd Skelton