I encountered a similar issue and sought assistance on this platform: How to modify a component on specific routes in Angular2
The crux of the problem lies in the limitation of using @CanActivate
or onActivate
exclusively. These utilities can only be applied to Components that are routed TO, not FROM. If, for instance, your app.component
contains a topbar or sidebar with the router-outlet
nested within its template, accessing route data becomes challenging.
Hence, a viable solution involves extending the default router-outlet
and incorporating your logic there.
By implementing a @RouteConfig
like the one below:
@RouteConfig([
{
path: '/login',
name: 'Login',
component: LoginComponent,
data: {
hideTopbar: true,
hideSidebar: true
}
},
and crafting a template for your app.component
as follows:
<div class="topbar" *ngIf="showTopbar">...</div>
<extended-router-outlet></extended-router-outlet>
You can manage this in your app.component
class:
export class AppComponent {
showTopbar:boolean;
showSidebar:boolean;
constructor(private _routingEventService:RoutingEventService) {
this._routingEventService.onRouteChanged().subscribe(routeData => {
this.showTopbar = !routeData.hideTopbar;
this.showSidebar = !routeData.hideSidebar;
});
}
}
utilizing a routed event service as described in the linked answer above:
@Injectable()
export class RoutingEventService {
private _eventEmitter: EventEmitter<any> = new EventEmitter();
routeIsChanging(obj:any) {
this._eventEmitter.emit(obj);
}
onRouteChanged() {
return this._eventEmitter;
}
}
Subsequently, create your new router-outlet
directive as follows:
@Directive({
selector: 'extended-router-outlet'
})
export class ExtendedRouterOutlet extends RouterOutlet {
private parentRouter:Router;
constructor( _elementRef: ElementRef,
_loader: DynamicComponentLoader,
_parentRouter: Router,
@Attribute('name') nameAttr: string,
private _routingEventService:RoutingEventService ) {
super(_elementRef, _loader, _parentRouter, nameAttr);
this.parentRouter = _parentRouter;
}
activate(nextInstruction: ComponentInstruction): Promise<any> {
this._routingEventService.routeIsChanging({
name: nextInstruction.routeName,
hideTopbar: nextInstruction.routeData.data['hideTopbar'],
hideSidebar: nextInstruction.routeData.data['hideSidebar']
});
return super.activate(nextInstruction);
}
}
This approach allows for the handling of various route-specific logic, such as authentication or role checks, as elaborated in my response to a related query:
Populating form fields after receiving HTTP response in Angular2
Hopefully, this explanation proves beneficial.