J'aimerais attacher un composant à une route de manière asynchrone, étant donné une condition .
L'exemple suivant, qui fonctionne (mais est asynchrone), charge un composant ou un autre en fonction du rôle de l'utilisateur:
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 },
]
Mais disons que nous voulons récupérer le rôle à partir d'une API, donc asynchrone . Quel est le moyen d'accomplir cela?
Angular 2 prend en charge le chargement paresseux au niveau du module. Les modules de fonctions sont chargés de manière asynchrone et non de composant . Vous pouvez créer ce module de fonctionnalité de composant . https://angular.io/docs/ts/latest/guide/ngmodule.html
Vous pouvez créer un fichier generic.module.ts contenant les deux composants dans le tableau de déclarations:
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 { }
ainsi, vous aurez un module contenant les modules que vous souhaitez charger.
La prochaine étape consistera à les charger de manière asynchrone à l'aide du compilateur: À l'intérieur de votre composant, procédez comme suit:
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);
}
}
J'espère que cela t'aides.
Vous pouvez simplement définir un composant de niveau supérieur, p.ex. DashboardComponent qui est inclus dans route/tableaux de bord
Le composant parent est alors censé charger les enfants dans son modèle en fonction de la condition asynchrone.
De cette façon, vous devrez également utiliser * ngIf mais au moins ne pas encombrer les modèles de composants enfants.
Étant donné que vous utiliserez une route pour l'un ou l'autre composant, l'une des solutions permettant de créer un autre composant pour cette route, son modèle pourrait alors faire référence aux deux composants, mais avec un ngIf comme ci-dessous:
<user-dashboard *ngIf="role==='user'"></user-dashboard>
<admin-dashboard *ngIf="role==='admin'"></admin-dashboard>
Je vous conseille de naviguer par programme en utilisant la méthode de navigation du routeur. Donc, vous listez toutes les routes possibles dans le fichier routeur. Ensuite, dans votre composant, vous appelez router.navigate () en fonction du cas spécifique.
Une très bonne solution pourrait être "Utiliser auth-guard". Vous pouvez essayer d'implémenter les interfaces CanActivate/CanLoad et placer votre condition dans cette classe.
Sur la base de la condition, les itinéraires sont activés.
Exemple:
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
}
}