Angular enables the components based development which helps you create small cohesive components to design the application in a manageable approach. This may also lead to a complex heirarchy among the components. Then you need a mechanism to communicate between these components which may be in two directions top-down and bottom-up.
In this post we will see an example of bottom-up approach to allow communication from the child component to the parent component.
Lets say we have two components, ParentComponent
and ChildComponent
, with structure like this.
<parent-component> <child-component /> </parent-component>
The child-component
has a button called btnSearch
, which needs to invoke the parent-component's
function searchCalledByChild()
;
Lets walk through this example to see how we can achieve this behavior.
This is the child component's ts
file:
// child.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-child-component', templateUrl: './child-component.component.html', styleUrls: ['./child-component.component.css'] }) export class ChildComponentComponent implements OnInit { count: number = 0; child_msg : string = ""; constructor() { } ngOnInit(): void { } btnSearchClicked() { this.child_msg = "Clicked Counter: " + this.count++; } }
This will display a string child_msg
in html template, showing the counter for button clicks.
This is the parent component's ts
file:
// parent.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-parent-component', templateUrl: './parent-component.component.html', styleUrls: ['./parent-component.component.css'] }) export class ParentComponentComponent implements OnInit { parent_msg : string = ""; chil_msg_inside_parent : string = ""; constructor() { } ngOnInit(): void { } //method in parent class, this needs to be invoked //when button is clicked in child component searchCalledByChild(child_msg_received: string) { this.parent_msg = "Message from parent component"; //child_msg_received is the data passed from child component. this.chil_msg_inside_parent = child_msg_received; } }
To enable the parent component to receive notification of child-component's event, we have to makes these changes in child-component's ts
file:
First import Output
and EventEmitter
from '@angular/core'
import { Output, EventEmitter } from '@angular/core';
Decorate a property with @Output()
. Here searchButtonClickedEvent
is the name of the property declared as EventEmitter
, which means it's an event.
@Output() searchButtonClickedEvent = new EventEmitter<string>();
The type parameter we passed to EventEmitter<>
tells angular that this event will emit the string data.
Raise this event from child-component's local method btnSearchClicked()
using the emit()
function.
btnSearchClicked() { this.child_msg = "Clicked Counter: " + this.count++; this.searchButtonClickedEvent.emit(this.child_msg); }
Here is the html template for child-component:
<div style="background-color:grey;margin:10px;padding:10px;"> <button id="btnSearch" (click)="btnSearchClicked()">Click child</button> <p>Child Content: {child_msg}}</p> </div>
Now the child component is ready to emit events whenever the btnSearchClicked()
function is called. In this example we are calling this function from child-component's button click.
To enable the parent-component to receive this event, we will bind the parent' local method to the child's event. To bind the event we will use the same event property
of EventEmitter
we have defined in the child-component.
<div style="background-color:tan;margin:10px; padding:10px;"> <app-child-component (searchButtonClickedEvent)="searchCalledByChild($event)"> </app-child-component> <p>{{parent_msg}}</p> <p>Parent Content: {{chil_msg_inside_parent}}</p> </div>
This event binding, (searchButtonClickedEvent)="searchCalledByChild($event)
, connects the event in the child (searchButtonClickedEvent
) to the function in the parent(searchCalledByChild
).
The $event
parameter contains the data that we have passed from the child-compoment in the emit()
function.
The complete listing of the parent-component's ts
file will be look like this:
// parent.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-parent-component', templateUrl: './parent-component.component.html', styleUrls: ['./parent-component.component.css'] }) export class ParentComponentComponent implements OnInit { parent_msg : string = ""; chil_msg_inside_parent : string = ""; constructor() { } ngOnInit(): void { } //method in parent class, this needs to be invoked //when button is clicked in child component searchCalledByChild(child_msg_received: string) { this.parent_msg = "Message from parent component"; //child_msg_received is the data passed from child component. this.chil_msg_inside_parent = child_msg_received; } }
References: