I\'d like to attach a component to a route asynchronously, given a condition.
The following example, which works (but is asynchronous), loads one compon
You could create a generic.module.ts which will have both components in declarations array:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UserDashboardComponent } from './user-dashboard.component'
import { AdminDashboardComponent } from './admin-dashboard.component
@NgModule({
imports: [ BrowserModule ],
declarations: [ UserDashboardComponent,AdminDashboardComponent ]
})
export class GenericModule { }
this way you will have a module that contains the modules which you want to load.
Now next step will be to load them asynchronously using compiler: inside your component do following:
import {GenericModule} from './generic.module';
import { Component, Input,ViewContainerRef, Compiler, NgModule,ModuleWithComponentFactories,OnInit,ViewChild} from '@angular/core';
@Component({
selector: 'generic',
template: '<div #target></div>'
})
export class App implements AfterViewInit {
@ViewChild('target', {read: ViewContainerRef}) target: ViewContainerRef;
constructor(private compiler: Compiler) {}
ngAfterViewInit() {
this.createComponent('<u>Example template...</u>');
}
private createComponent(template: string,role:string) {
@Component({template: template});
const mod = this.compiler.compileModuleAndAllComponentsSync(GenericModule);
const factory = mod.componentFactories.find((comp) =>
//you can add your comparison condition here to load the component
//for eg. comp.selector===role where role='admin'
);
const component = this.target.createComponent(factory);
}
}
Hope this helps.
I advice you make use of navigating programatically using the router's navigate method . So you list all the posible routes in the router file .Then in your component you call router.navigate() based on the specific case .
Since you will be using one route for either component, one solution is create another component for that route then its template could refer to both components but with an ngIf like below:
<user-dashboard *ngIf="role==='user'"></user-dashboard>
<admin-dashboard *ngIf="role==='admin'"></admin-dashboard>
Angular 2 supports lazy loading at module level. Feature modules are loaded asynchronously, not component. You can make that component feature module. https://angular.io/docs/ts/latest/guide/ngmodule.html
Very good solution could be "Use auth-guard". You can try implementing interfaces CanActivate/CanLoad and put your condition in that class.
Based on condition, routes gets activated.
Example:
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot
} from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';
@Injectable()
export class AuthorizationGuard implements CanActivate {
constructor() {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
Observable<boolean> {
let url: string = state.url;
return this.canbeLoaded(url);
}
canbeLoaded(url: string): Observable<boolean> {
return Observable.of(true); //put your condition here
}
}
You could just define a higher-level component f.e. DashboardComponent which is included at route /dashboards
The parent component is then supposed to load the children in its template based on the asynchronous condition.
This way you will also need to use the *ngIf but at least its not cluttering the child components templates.