Angular Dynamic Component Loader Tutorial with Examples

Angular Dynamic Component Loader Tutorial with Examples

In the tutorial, grokonez.com shows how to dynamically load an Angular components by examples. What we introduce:

  • Create Anchor Directive
  • Dynamically Loading and Resolving Components

Related posts:
Angular 6 Component – How to create & integrate New Angular 6 Component
Angular 6 Routing/Navigation – with Angular Router Service

Overview

An Agnular application may need to load new components at runtime, so component’s templates are not always fixed.
The following examples shows how to build an dynamic news banner.

angular-dynamic-loading-component-tutorial-with-examples-overview

New news components are added frequently so it is impractical to use a template with a static component structure.

Angular Anchor Directive

We need define an anchor point to tell Angular where to insert components for adding a new components:
Now we build an NewsDirective to mark valid insertion points in the template:


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

	@Directive({
	  selector: '[news-host]'
	})
	export class NewsDirective {
	  constructor(public viewContainerRef: ViewContainerRef) { }
	}
	

NewsDirective injects ViewContainerRef to access to the view container of the element that will host the dynamically added component.

news-host is used to apply the directive to the element.

Angular Dynamic Loading Components

We implement an NewsBannerComponent in news-banner.component.ts file.


	...

	@Component({
	  selector: 'app-news-banner',
	  template: `
				

Dynamic News Banner - Copyright by http://grokonez.com

` }) export class NewsBannerComponent implements OnInit, OnDestroy { ...

The element is where you apply the directive to dynamically load components.
The element doesn’t render any additional output.

Angular Resolving Components

NewsBannerComponent takes an array of NewsItem objects as input that comes NewsService.
NewsItem object contains component object to load and any data to bind to the component.


	import { Type } from '@angular/core';

	export class NewsItem {
	  constructor(public component: Type, public data: any) { }
	}
	

NewsService returns the actual news content for banner:


	import { Injectable } from '@angular/core';
	import { SportNewsComponent } from './sport-news/sport-news.component';
	import { NewsItem } from './news-item';
	import { BusinessNewsComponent } from './business-news/business-news.component';

	@Injectable({
	  providedIn: 'root'
	})
	export class NewsService {

	  getNews() {
		return [
		  new NewsItem(SportNewsComponent, {
			title: "2019 Women's World Cup: Spain's Women come back to beat South Africa",
			from: "euronews.com"
		  }),

		  new NewsItem(BusinessNewsComponent, {
			title: 'Walmart will save $30 million by putting new step stools in its warehouses',
			author: 'Lauren Thomas'
		  }),

		  new NewsItem(SportNewsComponent, {
			title: "Women's World Cup: Germany Women 1-0 China Women",
			from: 'bbc.com'
		  }),

		  new NewsItem(BusinessNewsComponent, {
			title: 'Elliott Management to acquire Barnes & Noble for $683 million',
			author: 'Lauren Hirsch'
		  })
		];
	  }
	}
	

NewsBannerComponent loop through the array of NewsItems and uses loadComponent() to load a new component every 3 seconds.


	export class NewsBannerComponent implements OnInit, OnDestroy {
	 
	  @Input() news: NewsItem[];
	  currentNewsIndex = -1;
	  @ViewChild(NewsDirective, { static: true }) newsHost: NewsDirective;
	  interval: any;

	  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

	  ngOnInit() {
		this.loadComponent();
		this.getNews();
	  }

	  ngOnDestroy(): void {
		clearInterval(this.interval);
	  }

	  loadComponent() {
		this.currentNewsIndex = (this.currentNewsIndex + 1) % this.news.length;
		let newsItem = this.news[this.currentNewsIndex];

		let componentFactory = this.componentFactoryResolver.resolveComponentFactory(newsItem.component);

		let viewContainerRef = this.newsHost.viewContainerRef;
		viewContainerRef.clear();

		let componentRef = viewContainerRef.createComponent(componentFactory);
		(componentRef.instance).data = newsItem.data;
	  }

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

NewsBannerComponent uses ComponentFactoryResolver to resolve a ComponentFactory for each specific component.
createComponent() method returns a reference to the loaded component. Use that reference to interact with the component by assigning to its properties or calling its methods.

Note: to ensure that the compiler generates a ComponentFactory for dynamically loaded components, we need add dynamically loaded components to the NgModule’s entryComponents array:


	entryComponents: [SportNewsComponent, BusinessNewsComponent],
	

NewsComponent Interface

To standardize the API for passing data to the components, we create an interface component: NewsComponent.


	export interface NewsComponent {
	  data: any;
	}

Then using it in all sub-news components:

SportNewsComponent:


	import { Component, OnInit, Input } from '@angular/core';
	import { NewsComponent } from '../news.component';

	@Component({
	  template: `
		

Sport News

{{data.title}}

from: {{data.from}}

` }) export class SportNewsComponent implements NewsComponent { @Input() data: any; }

BusinessNewsComponent:


	import { Component, OnInit, Input } from '@angular/core';
	import { NewsComponent } from '../news.component';

	@Component({
	  template: `
		

Business News

{{data.title}}

Author: {{data.author}}

` }) export class BusinessNewsComponent implements NewsComponent { @Input() data: any; }

Bootstrap App Component

We edit a bootstrap AppComponent that shows app-news-banner component. And it also injects NewsService to provide NewsItem data for NewsBannerComponent:


	import { Component } from '@angular/core';
	import { NewsItem } from './news-item';
	import { NewsService } from './news.service';

	@Component({
	  selector: 'app-root',
	  template: `
		
` }) export class AppComponent { news: NewsItem[]; constructor(private newsService: NewsService) { } ngOnInit() { this.news = this.newsService.getNews(); } }

Sourcecode

– Project structure

angular-dynamic-loading-component-tutorial-with-examples-project-structure

– Source Code:

Angular-Dynamic-Loading-Components



By grokonez | June 10, 2019.

Last updated on April 8, 2021.



Related Posts


49 thoughts on “Angular Dynamic Component Loader Tutorial with Examples”

  1. Ahaa, its nice dialogue regarding this post at this place at this weblog, I have read all that, so now me also commenting here. tastyandinteresting.be/beautiful-things/privatleasing-bil-bra-eller-dligt.php privatleasing bil bra eller dГҐligt

  2. Белорусский трикотаж Свитмода|Молодежная женская одежда Свитмода|Одежда женская больших размеров Свитмода Бай|

  3. Белорусский трикотаж Свитмода|Молодежная женская одежда Свитмода|Одежда женская больших размеров Свитмода Бай|

  4. I like the valuable info you provide in your articles. I’ll bookmark your blog and check again here regularly. I am quite certain I’ll learn plenty of new stuff right here! Good luck for the next! Kissee Kalvin Marja

  5. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. I have a dynamic component loader, and I need to pass in data through a service. I can get the data to display if I fire the function on

  6. Hello! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Anyways, I’m definitely happy I found it and I’ll be book-marking and checking back frequently!

  7. You made some decent points there. I looked on the internet for the topic and found most individuals will consent with your blog. Loni Willem Saloma

  8. Hello! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Anyways, I’m definitely happy I found it and I’ll be book-marking and checking back frequently!

  9. Hello! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Anyways, I’m definitely happy I found it and I’ll be book-marking and checking back frequently!

  10. Hello! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Anyways, I’m definitely happy I found it and I’ll be book-marking and checking back frequently!

  11. Hello! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Anyways, I’m definitely happy I found it and I’ll be book-marking and checking back frequently!

  12. Hello! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Anyways, I’m definitely happy I found it and I’ll be book-marking and checking back frequently!

  13. I do agree with all the ideas you have presented in your post. They are very convincing and will definitely work. Still, the posts are too short for novices. Could you please extend them a bit from next time? Thanks for the post. Analiese Crichton Malka

Got Something To Say:

Your email address will not be published. Required fields are marked *

*