๐งฝ 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>
Child template code: (child.component.html)
html
<div>
Child Input: <input type="text" />
</div>
Let's say we want to listen to a keydown
event that is emitted by the <input />
element above.
Solution:
Child
Template code (child.component.html):
<div>
Child Input: <input type="text" (keydown)="handleKeydown($event)" />
<p>Result from child component: {{ text }}</p>
</div>
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);
}
}
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>
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";
}
}
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 ๐