Angular 2: Inject a dependency into @CanActivate?

后端 未结 5 1170
心在旅途
心在旅途 2021-01-02 06:55

In Angular 2, you can specify a @CanActivate annotation for a component where you can determine if the component should be activated or not. The reason it\'s no

相关标签:
5条回答
  • 2021-01-02 07:00

    You have to inject it using injector. Just a quick copy paste from a project I'm doing:

    @CanActivate((next: ComponentInstruction, prev: ComponentInstruction) => {
    
      console.info('CanActivate hook! - can return boolean or Promise');
    
      var injector = Injector.resolveAndCreate([HTTP_PROVIDERS, YourService]);
      var yourService = injector.get(YourService);
      // do something with yourService
      return new Promise(function(resolve, reject) {
          resolve(true);
      });
    
    })
    

    HTTP_PROVIDERS you have to pass along if your service is for example injecting the HTTP service in the constructor.

    I use it to put an observable on the params of the next object. And the next object is your next "Component/state":

    @CanActivate((next: ComponentInstruction, prev: ComponentInstruction) => {
    
      console.info('properties component CanActivate hook! - can return boolean or Promise');
      var injector = Injector.resolveAndCreate([HTTP_PROVIDERS, PropertiesService]);
      var propertiesService = injector.get(PropertiesService);
      return new Promise(function(resolve, reject) {
          next.params['properties'] = propertiesService.getProperties();
          resolve(true);
      });
    
    })
    

    The PropertiesService calls a backend and returns an Observable that represents the data with properties

    0 讨论(0)
  • 2021-01-02 07:15

    Most solutions here will present problems with loading sub-dependencies from elsewhere in the hierarchy, because they create a new injector. Also, this results in additional (non-shared) services being instanced. I recommend following the pattern provided by Brandon in https://github.com/angular/angular/issues/4112

    He references this Plunk: http://plnkr.co/edit/SF8gsYN1SvmUbkosHjqQ?p=preview

    Its main idea is a singleton injector, which he saves when the app initializes. This provides access to the root dependencies you already have configured, and further allows your services to be shared as a singleton as they were probably intended:

    import {Injector} from 'angular2/angular2';
    let appInjectorRef: Injector;
    
    export const appInjector = (injector?: Injector):Injector => {
        if (injector) {
          appInjectorRef = injector;
        }
    
        return appInjectorRef;
    };
    
    bootstrap([ServiceYouNeed]).then((appRef) => {
        // store a reference to the injector
        appInjector(appRef.injector);
    });
    
    0 讨论(0)
  • 2021-01-02 07:18

    Angular 2.0 final solution:

    Since we now define a separate class which implements CanActivate, that class can be @Injectable, and another dependency can be provided in its constructor as per this answer.

    0 讨论(0)
  • 2021-01-02 07:21

    I don't know if its the best way, but these guys do it by extending and using its own <router-outlet> and override the CanActivate method:

    https://auth0.com/blog/2015/05/14/creating-your-first-real-world-angular-2-app-from-authentication-to-calling-an-api-and-everything-in-between/

    Also you could use routerOnActivate instead.

    https://angular.io/docs/js/latest/api/router/OnActivate-interface.html I hope this helps.

    0 讨论(0)
  • 2021-01-02 07:23

    Here (https://gist.github.com/clemcke/c5902028a1b0934b03d9) is how to test the addInjector() solution that @shannon references:

    beforeEachProviders(()=>[PERSON_SERVICE_PROVIDERS]);
    
    beforeEach(inject([PersonService],()=>{
      let injector = Injector.resolveAndCreate([PERSON_SERVICE_PROVIDERS]);
      appInjector(injector);
    }));
    
    0 讨论(0)
提交回复
热议问题