web-dev-qa-db-fra.com

Angular 2: Comment charger conditionnellement un composant dans une route de manière asynchrone?

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?

18
Alex JM

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

8
Manish

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.

8
Bhushan Gadekar

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.

4
tom

É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>
2
jovani

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. 

1
luxury

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
  }
}
0
srikanth_k