Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular2: how to get Full path on CanLoad guard while maintaining redirect url

I am using angular 2.4 version and router version "^3.4.10".

I am trying to handle redirect url using auth guard service.

When user hit url 'domain/assignment/3/detail' and if user is not login then user redirected to 'domain/login' page. and when user successfully login in to system then redirected to 'domain/assignment/3/detail' previous url which user tries to access.

I have implemented CanLoad guard on assignment module. so when user tries to access url 'domain/assignment/3/detail' and if user is not login, url stores into redirectUrl property of authservice (this.authService.redirectUrl).

so here is the issue comes in my case. i am not able to get full path of the url which user hit. i am getting 'assignment' instead 'assignment/3/detail' within CanLoad guard. how can i get full path so that i can redirect user to proper path within CanLoad guard.

CanLoad:

 canLoad(route: Route): boolean {

            let url = `/${route.path}`; // here i got url path 'assignment' instead 'assignment/3/detail'

            return this.checkLogin(url);
        }

Main routing app.routes.ts

const routes: Routes = [
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'login', component: LoginComponent},
{
    path: 'assignment',
    loadChildren: './assignment/assignment.module#AssignmentModule',
    canLoad: [AuthGuard]
},
{ path: '**', redirectTo: '', pathMatch: 'full' }];

Assignment routing: assignment-routing.ts

       const assignmentRoutes: Routes = [
        {
            path: '',
            component: AssignmentComponent,
            canActivate: [AuthGuard]
            children: [
                {
                    path: '',
                    canActivateChild: [AuthGuard],
                    children: [
                        {
                            path: ':assignmentId/detail', component: AssignmentDetailComponent,
                            canActivate: [AuthGuard]

                        }
                      ]
                  }]
         }];

AuthGuard: auth-gurad.service.ts

import { Injectable } from '@angular/core';
import {
    CanActivate, Router,
    ActivatedRouteSnapshot,
    RouterStateSnapshot,
    CanActivateChild,
    NavigationExtras,
    CanLoad, Route
} from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
    constructor(private authService: AuthService, private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        let url: string = state.url;
        return this.checkLogin(url);
    }

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

    canLoad(route: Route): boolean {

        let url = `/${route.path}`; // here i got url path 'assignment' instead 'assignment/3/detail'

        return this.checkLogin(url);
    }



     checkLogin(url: string): boolean {
            if (this.authService.isLoggedIn) {
                if(this.authService.redirectUrl!=null){
                    let redirectUrl = this.authService.redirectUrl;
                    this.authService.redirectUrl = null;
                    this.this.router.navigate([redirectUrl]);
                }
                return true;
                }

        // Store the attempted URL for redirecting
        this.authService.redirectUrl = url;

        // Navigate to the login page 
        this.router.navigate(['/login']);

        return false;
    }
}
like image 862
Krishna Avatar asked Jun 14 '17 07:06

Krishna


2 Answers

If you look the signature of the canLoad method, there is is a second parameter segments which you can use to generate the url.

canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean

You can generate the full path using following code:

canLoad(route: Route, segments: UrlSegment[]): boolean {

  const fullPath = segments.reduce((path, currentSegment) => {
    return `${path}/${currentSegment.path}`;
  }, '');

  console.log(fullPath);

}

Note: With this method you will get the full path, but you will not get any query parameters.

like image 163
Abbas Siddiqi Avatar answered Nov 06 '22 19:11

Abbas Siddiqi


I have this exact same problem. These issues are related

  • https://github.com/angular/angular/issues/17359
  • https://github.com/angular/angular/issues/12411

And they even have an open PR about this which hasn't been merged yet

  • https://github.com/angular/angular/pull/13127

The workaround for now seems to be to replace the canLoad method with the canActivate, there you can have access to the full path, the bad thing of course is that you're loading the module

Edit: Also for you Assignment routing, there's no need to call canActivate for each child route. Have it defined on the parent route should apply the guard for all child routes.

like image 7
Edwin Vasquez Avatar answered Nov 06 '22 21:11

Edwin Vasquez