Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: How to conditionally load a Component in a Route asynchronously?

Tags:

I'd like to attach a component to a route asynchronously, given a condition.

The following example, which works (but is asynchronous), loads one component or another depending on the user role:

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 }, ] 

But, let's say we want to retrieve the role from an API, thus asynchronous. What's the way to accomplish that?

like image 357
Alex JM Avatar asked Sep 25 '16 16:09

Alex JM


1 Answers

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.

like image 130
Bhushan Gadekar Avatar answered Sep 23 '22 06:09

Bhushan Gadekar