1.首先定义一个辅助指令
辅助指令用来标记 动态组件 的插入点
// ad.directive.ts
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[adHost]',
})
export class AdDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
2.定义需要动态插入的组件
// ad.component.ts 组件统一接口
export interface AdComponent {
data: any;
}
// hero-job-ad.component.ts 动态组件
import { Component, Input } from '@angular/core';
import { AdComponent } from './ad.component';
@Component({
template: `
<div class="job-ad">
<h4>{{data.headline}}</h4>
{{data.body}}
</div>
`
})
export class HeroJobAdComponent implements AdComponent {
@Input() data: any;
}
// hero-profile.component.ts 动态组件
import { Component, Input } from '@angular/core';
import { AdComponent } from './ad.component';
@Component({
template: `
<div class="hero-profile">
<h3>Featured Hero Profile</h3>
<h4>{{data.name}}</h4>
<p>{{data.bio}}</p>
<strong>Hire this hero today!</strong>
</div>
`
})
export class HeroProfileComponent implements AdComponent {
@Input() data: any;
}
3.定义Service获取所有的动态组件
// ad.service.ts
import { Injectable } from '@angular/core';
import { HeroJobAdComponent } from './hero-job-ad.component';
import { HeroProfileComponent } from './hero-profile.component';
import { AdItem } from './ad-item';
@Injectable()
export class AdService {
getAds() {
return [
new AdItem(
HeroProfileComponent,
{ name: 'Bombasto', bio: 'Brave as they come' }
),
new AdItem(
HeroProfileComponent,
{ name: 'Dr IQ', bio: 'Smart as they come' }
),
new AdItem(
HeroJobAdComponent,
{ headline: 'Hiring for several positions', body: 'Submit your resume today!' }
),
new AdItem(
HeroJobAdComponent,
{ headline: 'Openings in all departments', body: 'Apply today' }
)
];
}
}
// ad-item.ts 动态组件传参对象
import { Type } from '@angular/core';
export class AdItem {
constructor(public component: Type<any>, public data: any) {}
}
4.定义容器,动态展示
//ad-banner.component.ts
import { Component, ViewContainerRef, ComponentFactoryResolver, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import { AdItem } from './ad-item';
import { AdService } from './ad.service';
import { AdDirective } from './ad.directive';
import { AdComponent } from './ad.component';
@Component({
selector: 'app-ad-banner',
template: `
<div class="ad-banner-example">
<h3>Advertisements</h3>
<ng-template [adHost]="adItem"></ng-template>
</div>
`
})
export class AdBannerComponent implements OnInit, OnDestroy {
ads: AdItem[];
currentAdIndex = -1;
@ViewChild(AdDirective, {static: true}) adHost!: AdDirective;
interval: any = 0;
constructor(private componentFactoryResolver: ComponentFactoryResolver,
private adService: AdService){
this.ads = this.adService.getAds();
}
ngOnInit(): void {
this.loadComponent();
this.getAds();
}
ngOnDestroy() {
clearInterval(this.interval);
}
loadComponent() {
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
const adItem = this.ads[this.currentAdIndex];
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
const componentRef = viewContainerRef.createComponent<AdComponent>(componentFactory);
componentRef.instance.data = adItem.data;
}
getAds() {
this.interval = setInterval(() => {
this.loadComponent();
}, 3000);
}
}
网友评论