2

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!

4
  • What do you mean by "This click should handle 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?
    – Barremian
    Commented Jun 18, 2021 at 12:56
  • Yes, the component has the needed @Output() inside Commented Jun 18, 2021 at 13:02
  • What do then mean by the "add (click) handler" to the component? Do you wish to capture a mouse click over the entire component?
    – Barremian
    Commented Jun 18, 2021 at 13:06
  • Yes. the component is a chat message and need to handle mouse click on it: <div (click)="handler($event)"> Commented Jun 18, 2021 at 13:15

1 Answer 1

1

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

1
  • Yes, that's what I needed! Thanks Michael. )) You're the man! Commented Jun 18, 2021 at 13:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.