angulareventemitter

Angular EventEmitter goes from defined to undefined before event handler triggers


I am trying to pass information from a child component back to the parent component. Angular suggests using EventEmitter for this, so I imported Output and EventEmitter and set it up according to the specifications. Here's the code

import { Component, EventEmitter, OnInit, Output } from '@angular/core';

@Component({
  selector: 'app-map',
  standalone: true,
  imports: [],
  templateUrl: '../../assets/map-image.svg',
  styleUrl: './map.component.css'
})


export class MapComponent implements OnInit {
  map: any;
  @Output() selectedCountryEvent = new EventEmitter<string>();
  
  onClick(event: any) {
    console.log("Inside onClick: ");
    console.log(this.selectedCountryEvent);
    this.selectedCountryEvent.emit("hello click");
  }

  ngOnInit(): void {
    this.map = document.getElementsByTagName("svg");
    addEventListener("click", this.onClick);

    console.log("Inside ngOnInit: ");
    this.selectedCountryEvent.emit("hello world")
  }
}

The SVG is a file with a map on it and people click it to interact with it. I want to pass data from the map to the parent component (the app-root). But when I run this code, this is what happens:

  1. The selectedCountryEvent successfully emits to the parent in the ngOnInit function.
  2. When the click event is triggered, the onClick function executes. But when trying to access the selectedCountryEvent (EventEmitter object), the object is undefined and the emit fails.

Here's a picture of the console output generated by this: Output to console for code

It should work the same in both cases, but it doesn't. Does anyone know why the EventEmitter goes from defined during the initialization to undefined before the click event? Is there a way to stop this? All the help I've found just says that I must have set it up wrong, but I can successfully emit to the parent in the initialization. So something else is getting in the way.

(Edit: clarified what happens when the code is run)


Solution

  • By default, when you pass a method as an event listener, the context inside the listener will refer to the DOM element that triggered the event, not to the component or object where the method was originally defined.

    You can overcome that behavior by setting the current context to be the context inside the listener as the following:

    addEventListener('click', this.onClick.bind(this));