I am using an ngComponentOutlet
to dynamically display a caller-supplied component. My code knows absolutely nothing about the supplied component type. The template boils down to this:
<div [innerText]="options.title"></div>
<ng-container *ngComponentOutlet="options.componentType"></ng-container>
<button (click)="showInfo()">Info</button>
Speaking in a simplified manner, the caller for my UI passes a config object similar to the following:
export interface DisplayOptions<TComponent> {
readonly componentType: Type<TComponent>;
readonly title: string;
readonly onClickInfo: (cmp: TComponent) => void;
}
The UI surrounding the component outlet contains a couple of buttons, such as an Info button shown above. When that Info button is clicked, the onClickInfo
function should be invoked, which needs to receive a reference to the component.
Inside that showInfo()
function, how do I get my hands on the reference to the component instance in the component outlet?
You should be able to get a reference to this component using a @ViewChild
.
NgComponentOutlet
.@ViewChild
to get a reference to the component directive: @ViewChild(NgComponentOutlet, { static: false }) ngComponentOutlet: NgComponentOutlet;
A full example would look something like this:
import { Component, Type, ViewChild, NgComponentOutlet } from '@angular/core';
export interface DisplayOptions<TComponent> {
readonly componentType: Type<TComponent>;
readonly title: string;
readonly onClickInfo: (cmp: TComponent) => void;
}
@Component({
selector: 'app-dynamic',
template: `
<div [innerText]="options.title"></div>
<ng-container *ngComponentOutlet="options.componentType"></ng-componentOutlet>
<button (click)="showInfo()">Info</button>
`
})
export class DynamicComponent<TComponent> {
@ViewChild(NgComponentOutlet, { static: false }) ngComponentOutlet: NgComponentOutlet;
options: DisplayOptions<TComponent>;
showInfo() {
if (this.ngComponentOutlet) {
const componentInstance = this.ngComponentOutlet['_componentRef'].instance;
this.options.onClickInfo(componentInstance);
}
}
}
You query the ComponentOutlet
using the @ViewChild
and store it in the ngComponentOutlet
prop. showInfo()
can then access the ['_componentRef'].instance
prop of ngComponentOutlet
.
Another way to do this would be to go with an @Input
which is similar, but you'd have to update the HTML and pass in a primary key that you can use like an Id.