Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect to a different component inside @CanActivate in Angular2

Is there any way we can redirect to a different component from @CanActivate in Angular2 ?

like image 387
Vinz and Tonz Avatar asked Jan 10 '16 23:01

Vinz and Tonz


People also ask

What happens when CanActivate returns false?

CanActivatelink If any guard returns false , navigation is cancelled. If any guard returns a UrlTree , the current navigation is cancelled and a new navigation begins to the UrlTree returned from the guard.

Which is used to redirect to error component?

We use the wildcard path denoted by ** to catch any non existing routes and we use the redirectTo property to redirect them to the /404 path which maps to the not found component.

Can you activate guard?

What is CanActivate Guard. The Angular CanActivate guard decides, if a route can be activated ( or component gets rendered). We use this guard, when we want to check on some condition, before activating the component or showing it to the user.


3 Answers

As of today, with latest @angular/router 3.0.0-rc.1, here are a couple of references on how to do that through CanActivate guards on routes:

  1. angular 2 reference
  2. Two answers to this SO question, by Nilz11 and by Jason

The main gist of logic looks like:

// ...
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  if (this.authService.isLoggedIn) {
    // all ok, proceed navigation to routed component
    return true;
  }
  else {
    // start a new navigation to redirect to login page
    this.router.navigate(['/login']);
    // abort current navigation
    return false;
  }
}
like image 187
superjos Avatar answered Oct 22 '22 11:10

superjos


Your guard can easily just be an injectable which, as such, can include its own injectables. So we can simply inject the router, in order to redirect. Don't forget to add the service as a provider in your app module.

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private router: Router, private authService: AuthService) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
    if (!authService.isAuthenticated()) {
      this.router.navigate(['/login']);
      return false;
    }
    return true;
  }
}

export const ROUTES: Routes = [
  {path: 'login', component: LoginComponent},
  {path: 'protected', loadChildren: 'DashboardComponent', canActivate: [AuthGuard]}
];
like image 13
Stephen Paul Avatar answered Oct 22 '22 11:10

Stephen Paul


Yes, you can! Doing this will prevent your component from instantiating for nothing.

First, make a new file src/app-injector.ts

let appInjectorRef;

export const appInjector:any = (injector = false) => {
    if (!injector) {
        return appInjectorRef;
    }

    appInjectorRef = injector;

    return appInjectorRef;
};

Then, get the reference from bootstrap

// ...
import {appInjector} from './app-injector';
// ...


bootstrap(App, [
  ROUTER_PROVIDERS
]).then((appRef) => appInjector(appRef.injector));

Finally in your function

// ...
import {appInjector} from './app-injector';
// ...

@CanActivate((next, prev) => {
  let injector = appInjector();
  let router = injector.get(Router);

  if (42 != 4 + 2) {
    router.navigate(['You', 'Shall', 'Not', 'Pass']);
    return false;
  }

  return true;
})

Et voilà !

It was discussed here https://github.com/angular/angular/issues/4112

You can find a complete example here http://plnkr.co/edit/siMNH53PCuvUBRLk6suc?p=preview by @brandonroberts

like image 12
Druxtan Avatar answered Oct 22 '22 09:10

Druxtan