Loading Angular Components Dynamically
Tags: angular, webdev, programming, javascript
Published: 2021-01-23 00:19:59

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

 Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.

In this article, we’ll look at how to load and display Angular components dynamically.

Dynamic Component Loader
========================

We can load components by using the `ComponentFactoryResolver` to load multiple dynamic components.

Also, we have to make a directive to host the components.

First, we have to create the following components and directives by running the following commands:

```
ng g directive BannerHost  
ng g component Foo  
ng g component Bar
```

Then we write the following code:

`app.module.ts` :

```
import { BrowserModule } from '@angular/platform-browser';  
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';  
import { AppComponent } from './app.component';  
import { FooComponent } from './foo/foo.component';  
import { BarComponent } from './bar/bar.component';  
import { BannerHostDirective } from './banner-host.directive';

@NgModule({  
  declarations: [  
    AppComponent,  
    FooComponent,  
    BarComponent,  
    BannerHostDirective  
  ],  
  imports: [  
    BrowserModule,  
    AppRoutingModule  
  ],  
  providers: [],  
  bootstrap: [AppComponent],  
  entryComponents: [  
    FooComponent,  
    BarComponent,  
  ]  
})  
export class AppModule { }
```

`banner-host.directive.ts` :

```
import { Directive, ViewContainerRef } from '@angular/core';

@Directive({  
  selector: '[banner-host]'  
})  
export class BannerHostDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}
```

`bar.component.html` :

```
bar
```

`foo.component.ts` :

```
import { Component, OnInit, Input } from '@angular/core';

@Component({  
  selector: 'app-foo',  
  templateUrl: './foo.component.html',  
  styleUrls: ['./foo.component.css']  
})  
export class FooComponent implements OnInit {  
  @Input() data: string; constructor() { } 

  ngOnInit() {  
  }
}
```

`foo.component.html` :

```
foo {{data}}
```

`app.component.ts` :

```
import { Component, ComponentFactoryResolver, ViewChild } from '@angular/core';  
import { FooComponent } from './foo/foo.component';  
import { BannerHostDirective } from './banner-host.directive';  
import { BarComponent } from './bar/bar.component';

@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']  
})  
export class AppComponent {  
  interval: any;  
  currentBannerIndex: number = -1;  
  banners = [FooComponent, BarComponent]  
  @ViewChild(BannerHostDirective, { static: true }) bannerHost: BannerHostDirective;  

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { } 

  ngOnInit() {  
    this.loadComponent();  
    this.getBanners();  
  } ngOnDestroy() {  
    clearInterval(this.interval);  
  }

  loadComponent() {  
    this.currentBannerIndex = (this.currentBannerIndex + 1) % this.banners.length;  
    const bannerItem = this.banners[this.currentBannerIndex];
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(bannerItem);  
    const viewContainerRef = this.bannerHost.viewContainerRef;  
    viewContainerRef.clear();  
    const componentRef = viewContainerRef.createComponent(componentFactory);  
    if (componentRef.instance.constructor === FooComponent) {  
      (<FooComponent>componentRef.instance).data = 'hello';  
    }  
  } 

  getBanners() {  
    this.interval = setInterval(() => {  
      this.loadComponent();  
    }, 3000);  
  }  
}
```

`app.component.html` :

```
<ng-template banner-host></ng-template>
```

In the code above, we created the `banner-host` directive to inject the component that we’re going to load.

We applied that to `ng-template` in `app.component.html` .

`FooComponent` takes a `data` input that we’re going to set.

Then the components are loaded in `AppComponent` .

The `loadComponent` method in `AppComponent` by going through the banners that we defined in the `banners` array.

We changed the `currentBannerIndex` every 3 seconds as indicated by the `getBanners` method.

The actual component loading is done by the following code:

```
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(bannerItem);  
const viewContainerRef = this.bannerHost.viewContainerRef;  
viewContainerRef.clear();  
const componentRef = viewContainerRef.createComponent(componentFactory);  
if (componentRef.instance.constructor === FooComponent) {  
  (<FooComponent>componentRef.instance).data = 'hello';  
}
```

In the code above, we run the `this.componentFactoryResolver.resolveComponentFactory` method with the `bannerItem` as set by:

```
const bannerItem = this.banners[this.currentBannerIndex];
```

Then we clear the current view by writing:

```
const viewContainerRef = this.bannerHost.viewContainerRef;  
viewContainerRef.clear();
```

Next, we load the component by writing:

```
const componentRef = viewContainerRef.createComponent(componentFactory);
```

Finally, we check that the component is an instance of the `FooComponent` . If it is, then we load the string `data` property as indicated in the `data` field of `FooComponent` as follows:

```
if (componentRef.instance.constructor === FooComponent) {  
  (<FooComponent>componentRef.instance).data = 'hello';  
}
```

We used `componentRef.instance.constructor` to get which component instance is loaded.

Then if the component is an instance of `FooComponent` , we cast it to the `FooComponent` and set the `data` property of it to `'hello'` as follows:

```
(<FooComponent>componentRef.instance).data = 'hello';
```

In the end, we should see `foo hello` and `bar` displayed one after the other in a 3-second cycle.

Conclusion
==========

Displaying multiple Angular components dynamically involves several steps.

First, we have to create a directive to inject the components that we want to load.

Then we have to add an `ng-template` with the directive that we just created applied to it.

Next, we clear the existing view and use the `ComponentFactoryResolver` to clear the screen and then load the component that we want to load.

We can check the instance of the component that’s loaded and then do different things according to what component instance is loaded.