The answers are already available here and here.
I'd combine them here with an adjustment from the second answer. Instead of the Angular Renderer, I'd use the RxJS fromEvent
function to get the events. Additionally RxJS Subject
+ takeUntil
is used to close open subscriptions. See here for more info.
Try the following
import { fromEvent, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export class AppComponent implements OnDestroy {
closed$ = new Subject<any>();
@ViewChild('container', { read: ViewContainerRef })
container: ViewContainerRef;
private _counter = 1;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
add(): void {
// create the component factory
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
DynamicComponent
);
// add the component to the view
const viewContainerRef = this.container.createComponent(componentFactory);
// pass some data to the component
viewContainerRef.instance.index = this._counter++;
// get `@Output` emitter from the component
viewContainerRef.instance.emitter
.pipe(takeUntil(this.closed$))
.subscribe((event: any) => this.clickHandler(event));
// add `click` event handler to the component
fromEvent(viewContainerRef.location.nativeElement, 'click')
.pipe(takeUntil(this.closed$))
.subscribe((event: any) => this.clickHandler(event));
}
clickHandler(event?: any) {
console.log(event);
}
ngOnDestroy() {
this.closed$.next(); // <-- close open subscriptions
}
}
Working example: Stackblitz (extended from here).
EventEmitter($event)
"? Is there an@Output()
variable in this dynamic component that should also be handled by the same event handler as the(click)
event's?