9. Dynamic Components
AppComponent:
import { Component, OnInit } from '@angular/core';
import { AdService } from './ad.service';
import { AdItem } from './ad-banner.component';
@Component({
selector: 'app-root',
template: `
<h1>{{ title }}</h1>
<div class="left">
<div>
<app-add-banner [ads]="ads"></app-add-banner>
</div>
</div>
<div class="right">
<img [src]="imageUrl" class="img-round" alt="princess image">
</div>
`,
styles: ['h1 { font-weight: bold; }']
})
export class AppComponent implements OnInit {
title = 'Tour of Technologies';
imageUrl = '../assets/polymer1.jpg-large';
ads: AdItem[];
constructor(private adService: AdService) { }
ngOnInit() {
this.ads = this.adService.getAds();
}
}
AdService:
import { Injectable } from '@angular/core';
import { TechnologyAdComponent, TechnologyProfileComponent } from './ad.component';
import { AdItem } from './ad-banner.component';
@Injectable()
export class AdService {
getAds() {
return [
new AdItem(TechnologyProfileComponent,
{ name: 'Angular 5', bio: 'One Framework. Mobile & Desktop'}),
new AdItem(TechnologyProfileComponent,
{ name: 'AngularDart', bio: 'Productivity, Performance & Stability'}),
new AdItem(TechnologyAdComponent,
{ headline: 'Create new Single Page Applications',
body: 'Create new Web, Mobile, Hybrid, Native Apps today!'}),
new AdItem(TechnologyAdComponent,
{ headline: 'Read the Angular Documentation now',
body: 'Code, Reproduce the Angular Codebase on GitHub today.'})
];
}
}
Technology Components:
import { Component, Input } from '@angular/core';
import { AdComponent } from './ad-banner.component';
@Component({
template: `
<div class="ad">
<h4>{{ data.headline }}</h4>
{{ data.body }}
</div>
`
})
export class TechnologyAdComponent implements AdComponent {
@Input() data: any;
}
@Component({
template: `
<div class="profile">
<h3>Featured Technology Profile</h3>
<h4>{{ data.name }}</h4>
<p>{{ data.bio }}</p>
<strong>Build an app with this technology now!</strong>
</div>
`
})
export class TechnologyProfileComponent implements AdComponent {
@Input() data: any;
}
AdBannerComponent:
import { Component, Type, Input, AfterViewInit, ViewChild,
ComponentFactoryResolver, OnDestroy } from '@angular/core';
import { AdDirective } from './ad.directive';
export class AdItem {
constructor(public component: Type<any>, public data: any) { }
}
export interface AdComponent {
data: any;
}
@Component({
selector: 'app-add-banner',
template: `
<div class="ad-banner">
<h3>Advertisements</h3>
<ng-template adHost></ng-template>
</div>
`
})
export class AdBannerComponent implements AfterViewInit, OnDestroy {
@Input() ads: AdItem[];
currentAddIndex: number = -1;
@ViewChild(AdDirective) adHost: AdDirective;
subscription: any;
interval: any;
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
ngAfterViewInit() {
this.loadComponent();
this.getAds();
}
loadComponent() {
this.currentAddIndex = (this.currentAddIndex + 1) % this.ads.length;
const adItem = this.ads[this.currentAddIndex];
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
(<AdComponent>componentRef.instance).data = adItem.data;
}
getAds() {
this.interval = setInterval(() => {
this.loadComponent();
}, 3000);
}
ngOnDestroy() {
clearInterval(this.interval);
}
}
AdDirective:
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[adHost]'
})
export class AdDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
Sample CSS:
.profile {
border: 1px solid gray;
padding: 5px;
padding-bottom: 20px;
padding-left: 20px;
border-radius: 10px;
background-color: #ffe6e6;
color: black;
}
.ad {
border: 1px solid grey;
padding: 5px;
padding-bottom: 20px;
padding-left: 20px;
border-radius: 10px;
background-color: #ff4d4d;
color: white;
}
.ad-banner {
width: 400px;
}
AppModule(entry components):
entryComponents: [ TechnologyAdComponent, TechnologyProfileComponent ],
Let's view the results in our Chromium Browser: