简体   繁体   中英

Angular2 Router - Anyone know how to use canActivate in app.ts so that I can redirect to home page if not logged in

Angular2 Router - Anyone know how to use canActivate in app.ts so that I can redirect to home page if not logged in

I'm using typescript and angular 2.

Current attempt under my constructor in my app.ts file:

   canActivate(instruction) {           
               console.log("here - canActivate");
               console.log(instruction);

               this.router.navigate(['Home']);  
   }

It currently doesnt get hit. Any idea why?

So the documentation looks like this is what it exports.

export CanActivate(options : CanActivateAnnotation) : (hook: (next: ComponentInstruction, prev: ComponentInstruction) =>
                     Promise<boolean>| boolean) => ClassDecorator

@CanActivate((next, prev) => {
      // This must prove to be true for the component @ this route to load
      if(next.urlPath != '/Login'){ 
         return Promise.resolve(this._authService.getIsAuth() 
         && localStorage.getItem('authToken')
      }
      /*
       If CanActivate returns or resolves to false, the navigation is 
       cancelled. If CanActivate throws or rejects, the navigation is also
       cancelled. If CanActivate returns or resolves to true, navigation 
       continues, the component is instantiated, and the OnActivate hook of 
       that component is called if implemented.
      */
   }
);

At the bottom of the Angular2 documentation they add this snippet : exported from angular2/router https://angular.io/docs/ts/latest/api/router/CanActivate-decorator.html

So if you are looking to do redirection from a higher level. You would not use the CanActivate decorator you would do the following.

import {Directive, Attribute, ElementRef, DynamicComponentLoader} from 'angular2/core';
import {Router, RouterOutlet, ComponentInstruction} from 'angular2/router';
import {Login} from '../login/login';
import {UserService} from '../../Services/userService'; // a service to handle auth

@Directive({
  selector: 'router-outlet'
})
export class AuthRouterOutlet extends RouterOutlet {
  publicRoutes: any;
  private parentRouter: Router;

  constructor(private _userService:UserService, _elementRef: ElementRef, _loader: DynamicComponentLoader,
              _parentRouter: Router, @Attribute('name') nameAttr: string) {
    super(_elementRef, _loader, _parentRouter, nameAttr);

    this.parentRouter = _parentRouter;
    this.publicRoutes = {
      '/login': true,
      '/signup': true
    };
    // publicRoutes will be the routes auth is not needed for.
  }

  activate(instruction: ComponentInstruction) {
    var url = this.parentRouter.lastNavigationAttempt;
    if (!this.publicRoutes[url] && this._userService.getAuth()) {
      // todo: redirect to Login, may be there a better way?
      this.parentRouter.navigateByUrl('/login');
    }
    return super.activate(instruction);
    // we return super.activate(instruction) here so the router can activate the requested route and it's components.
  }
}

This implementation handles any new request to a directive and runs the activate function where your route authentication logic will be. The code above would be called something like AuthRouterOutlet. and you would have to add it to your app.ts via the

directives: [ AuthRouterOutlet]

With the new beta release of the router, you can also see my answer here on how to use the CanActivate interface:

https://stackoverflow.com/a/38369948/1944351

Using the decorator as mentioned in other answer is fine too.

These answers are no longer valid in the RC candidate as of 22/6/16.

There is a lot of talk a new solution for @CanActivate annotation but you can revert back to using the angular-2/router-deprecated version in the interim.

If you want to follow the updates to this area if you want to use the newer router implementation please check out these two github issues:

Sorry there is no complete answer right now, if I see any further progress on this I'll update this reply. I'm searching for an elegant solution as well.

For the interim I just used a ngIf='fooObject' in a div to check for object being used in a child directive is populated/truthy and then render the rest of the components html. It's not ideal but it does work consistently right now. May help you or not depending on your use case. I don't need to redirect, only check my data has resolved for the display of my component.

From here:

https://angular.io/docs/ts/latest/api/router/CanActivate-decorator.html

CanActivate is an annotation, not a function. You use it like this:

@Component({selector: ... })
@CanActivate(()=>console.log('Should the component Activate?'))
class AppComponent {

}

routerOnActivate IS a function you use inside your component:

https://angular.io/docs/ts/latest/api/router/OnActivate-interface.html

@CanActivate was removed. See more details here .

You should now use route.canActivate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM