navigationend - Angular 2: ¿Cómo cargar condicionalmente un componente en una ruta de forma asíncrona?
router events subscribe angular 4 (6)
Me gustaría adjuntar un componente a una ruta de forma asíncrona, dada una condición .
El siguiente ejemplo, que funciona (pero es asíncrono), carga un componente u otro según la función del usuario:
import { UserDashboardComponent } from ''./user-dashboard.component''
import { AdminDashboardComponent } from ''./admin-dashboard.component''
const role = ''admin'' // Just for the example
const comp = role === ''admin'' ? AdminDashboardComponent : UserDashboardComponent
const routes: Routes = [
{ path: '''', component: comp },
]
Pero, digamos que queremos recuperar el rol de una API, por lo tanto asíncrono . ¿Cuál es la manera de lograr eso?
Angular 2 admite la carga perezosa a nivel de módulo. Los módulos de funciones se cargan de forma asíncrona, no componente. Usted puede hacer que el componente de módulo de características. https://angular.io/docs/ts/latest/guide/ngmodule.html
Dado que utilizará una ruta para cada componente, una solución es crear otro componente para esa ruta, entonces su plantilla podría referirse a ambos componentes pero con un ngIf como el siguiente:
<user-dashboard *ngIf="role===''user''"></user-dashboard>
<admin-dashboard *ngIf="role===''admin''"></admin-dashboard>
Le aconsejo que haga uso de la navegación programática utilizando el método de navegación del enrutador. Por lo tanto, enumera todas las rutas posibles en el archivo del enrutador. Luego, en su componente, llama a router.navigate () según el caso específico.
Muy buena solución podría ser "Use auth-guard". Puede intentar implementar las interfaces CanActivate / CanLoad y poner su condición en esa clase.
Según la condición, las rutas se activan.
Ejemplo:
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
}
}
Podría crear un genérico.module.ts que tendrá ambos componentes en la matriz de declaraciones:
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 { }
De esta manera, tendrá un módulo que contiene los módulos que desea cargar.
Ahora el siguiente paso será cargarlos de forma asincrónica usando el compilador: dentro de su componente haga lo siguiente:
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);
}
}
Espero que esto ayude.
Simplemente podría definir un componente de nivel superior para DashboardComponent que se incluye en la ruta / paneles de control
Se supone entonces que el componente principal carga a los hijos en su plantilla basándose en la condición asíncrona.
De esta manera, también necesitará usar el * ngIf, pero al menos no está saturando las plantillas de componentes secundarios.