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:

results matching ""

    No results matching ""