После запуска документации Angular я обнаружил, что мне нужно передать данные в экземпляр componentRef, что-то вроде этого:
(<IHeader>componentRef.instance).data = headerItems.data;
После небольшого рефакторинга я закончил проходитьи компонент, и данные через службу, см. обновленный StackBlitz для рабочего примера.
В конце концов я посмотрю, чтобы передать несколько компонентов, но сейчас это работает.
header.component.html
<ng-template appHeaderHost></ng-template>
header.component.ts
/* ... */
export class HeaderComponent implements OnInit {
@ViewChild(HeaderHostDirective) headerHost: HeaderHostDirective;
subscriptionManager = new Subscription();
constructor(
private headerService: HeaderService,
private componentFactoryResolver: ComponentFactoryResolver
) {
const headerConfigSubscription = this.headerService.headerConfig$
.subscribe((headerItems: HeaderItem) => {
this.loadComponent(headerItems);
});
this.subscriptionManager
.add(headerConfigSubscription);
}
ngOnInit() {
}
loadComponent(headerItems: HeaderItem) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(headerItems.component);
const viewContainerRef = this.headerHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
(<IHeader>componentRef.instance).data = headerItems.data ? headerItems.data : null;
}
ngOnDestroy() {
/**
* @description Unsubscribe from all subscriptions
* to prevent memory leaks
*/
this.subscriptionManager.unsubscribe();
}
}
header.service.ts
/* ... */
export class HeaderService {
private headerConfigSource = new Subject<any>();
headerConfig$ = this.headerConfigSource.asObservable();
constructor() { }
configureHeaderItems(headerItems: HeaderItem) {
this.headerConfigSource.next(headerItems);
}
}
header.ts
/* ... */
export interface IHeader {
data: any;
}
export interface IHeaderItem {
component: Type<any>;
data?: any;
}
export class HeaderItem implements IHeaderItem {
constructor(
public component: Type<any>,
public data?: any
) {
this.component = component;
this.data = data;
}
}
main.component.html
<app-header></app-header>
main.component.ts
export class MainComponent implements OnInit {
headerItems: HeaderItem;
constructor(private headerService: HeaderService) { }
ngOnInit() {
this.configureHeaderItems();
}
configureHeaderItems() {
this.headerItems = new HeaderItem(MainHeaderDetailsComponent, {});
this.getHeaderItemData();
}
/**
* @description This is where we would make the API call and get the data
* but we can mock it for now
*/
getHeaderItemData() {
const data = {
name: 'I am loaded dynamically!'
};
this.headerItems.data = data;
this.headerService.configureHeaderItems(this.headerItems);
}
}
main.module.ts
@NgModule({
/* ... */
// Need to add to entryComponents
entryComponents: [MainHeaderDetailsComponent]
})
export class AnswerSetModule { }
main-header-details.component.html
<p>
Header content. {{data.name}}
</p>
main-header-details.component.ts
/* ... */
export class MainHeaderDetailsComponent implements OnInit {
constructor() { }
@Input() data: any;
ngOnInit() {
}
}