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
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
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);
});
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.
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.
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);
}));