DEV Community

Cover image for 🧽 Clean Way to Listen to Events from Children Components in Angular
Antonio Pekeljevic
Antonio Pekeljevic

Posted on

🧽 Clean Way to Listen to Events from Children Components in Angular

I don't write much about Angular but as I am working on a project that uses Angular at the moment I thought why not share a thing or two that I found interesting.

As someone who is definitely not an Angular expert I was looking for a clean solution on how to listen for element events that are part of a child component's template.

This is of course quite a trivial thing but it might be of value to people who are starting with Angular and are facing the same problem.

Let's start.

Situation:

We want to listen to child component input element's events inside of the parent component. (do something with it in the parent)

Parent template code: (parent.component.html)



<div>
  <h1>Parent component</h1>
  <angular-child></angular-child>
</div>


Enter fullscreen mode Exit fullscreen mode

Child template code: (child.component.html)



<div>
  Child Input: <input type="text" />
</div>


Enter fullscreen mode Exit fullscreen mode

Let's say we want to listen to a keydown event that is emitted by the <input /> element above.

Solution:

problem solved

Child

Template code (child.component.html):



<div>
  Child Input: <input type="text" (keydown)="handleKeydown($event)" />
  <p>Result from child component: {{ text }}</p>
</div>


Enter fullscreen mode Exit fullscreen mode

Component code (child.component.ts):



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

@Component({
  selector: "angular-child",
  templateUrl: "./child.component.html",
  styles: ["div { background-color: red }"]
})
export class ChildComponent {
  @Output()
  keyAction: EventEmitter<KeyboardEvent> = new EventEmitter<KeyboardEvent>();

  text = "";

  handleKeydown(event: KeyboardEvent): void {
    this.text = event.key;
    this.keyAction.emit(event);
  }
}


Enter fullscreen mode Exit fullscreen mode

Basically we are just having a method that receives the KeyboardEvent on a (keydown) event in which the text is saved to a variable and it uses an EventEmitter marked with an @Output() decorator. (so that we can later catch it in the parent)

Parent

Template code (parent.component.html):



<div>
  <h1>Parent component</h1>
  <angular-child (keyAction)="handleKeyAction($event)"></angular-child>
  <p>Result from parent component: {{ keyPressed }}</p>
</div>


Enter fullscreen mode Exit fullscreen mode

Component code (parent.component.ts):



import { Component } from "@angular/core";

@Component({
  selector: "angular-parent",
  templateUrl: "./parent.component.html",
  styleUrls: ["./parent.component.css"]
})
export class ParentComponent {
  keyPressed = "";

  handleKeyAction(event: KeyboardEvent): void {
    this.keyPressed = event.key + " from Parent";
  }
}


Enter fullscreen mode Exit fullscreen mode

Inside of the parent, we are calling a method each time the (keyAction) event has been emitted from the child. In that method we can do whatever we want with the received data. In this case we are just getting the key and adding some text to it to indicate that it has been changed before storing it to a variable.

Full code example on Codesandbox:

Again, it's not much but I hope somebody will find it helpful as it might not be an obvious solution at first.

Leave a comment with your opinion about the solution 😄

Buy Me a Coffee at ko-fi.com

Top comments (0)