I had this problem and came across your post in my search for answers. Finding none -- and having some time today -- I came up with a solution I thought you might be interested in. I created a "CompositeRouteGuard":
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import {Injectable, Injector} from '@angular/core';
import { Observable } from "rxjs";
@Injectable()
export class CompositeRouteGuard implements CanActivate {
constructor( protected router: Router,
protected injector: Injector ) {
}
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> {
var compositeCanActivateObservable: Observable<boolean> = Observable.of(true);
let routeGuards = route.data.routeGuards;
if(routeGuards){
for( var i = 0; i < routeGuards.length; i++ ){
let routeGuard = this.injector.get(routeGuards[i]);
let canActivateObservable = routeGuard.canActivate(route, state);
compositeCanActivateObservable = compositeCanActivateObservable.flatMap( (bool) => {
if(!bool){
return Observable.of(false);
}
else{
return canActivateObservable;
}
});
}
}
return compositeCanActivateObservable;
}
}
That requires a little extra configuration in your routes.ts. You need to add a "routeGuards" array to the data element of the route.
const routes: Routes = [
{
path: '...',
component: AComponent,
data: { routeGuards: [ FooRouteGuard, BarRouteGuard, BazRouteGuard ] },
canActivate: [ CompositeRouteGuard ]
},
...
I only cared about the canActivate action, but you should be able to easily extend this, to say "canDeactivate" (for example) if you need to.
Now my route guards run "in order" with "and" semantics (all must succeed for route to be activated).