Angry Beaver
Angry Beaver

Reputation: 465

Angular - dynamic component - bind (click) event

I'm creating a component dynamically and I need to add (click) handler with $event as a parameter at this dynamic component like we do this at HTML template <div (click)="clickHandler($event)">

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
const viewContainerRef = this.viewContainerRef.createComponent(componentFactory);

viewContainerRef.instance.message = componentData.message;

This click should handle EventEmitter($event)

How do I do this? Thanks for advance!

Upvotes: 2

Views: 2763

Answers (1)

Barremian
Barremian

Reputation: 31125

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).

Upvotes: 1

Related Questions