In this tutorial, we will learn how to Pass data from child to Parent Component in Angular. In the previous tutorial, we looked at how the pass data from parent to the child component by setting its input property. The Child can send data to Parent by raising an event, Parent can interact with the child via local variable or Parent can call @ViewChild on the child. We will look at all those options in this article.
Table of Contents
Pass data from Child to parent component
There are three ways in which the parent component can interact with the child component
- Listens to Child Event
- Uses Local Variable to access the child
- Uses a @ViewChild to get the reference to the child component
Let us look at each of those scenarios in detail
Parent listens for child event
The Child Component exposes an EventEmitter Property. This Property is adorned with the @Output decorator. When Child Component needs to communicate with the parent it raises the event. The Parent Component listens to that event and reacts to it.
EventEmitter Property
To Raise an event, the component must declare an EventEmmitter Property. The Event can be emitted by calling the .emit() method
For Example
1 2 3 | countChanged: EventEmitter<number> = new EventEmitter() |
And then call emit method passing the whatever the data you want to send as shown below
1 2 3 | this.countChanged.emit(this.count); |
@Output Decorator
Using the EventEmitter Property gives the components ability to raise an event. But to make that event accessible from parent component, you must decorate the property with @Output decorator
How to Pass data to parent component using @Output
In the child component
- Declare a property of type EventEmitter and instantiate it
- Mark it with a @Output Decorator
- Raise the event passing it with the desired data
In the Parent Component
- Bind to the Child Component using Event Binding and listen to the child events
- Define the event handler function
Passing data to parent component Via Events (Example)
Now let us build an application to demonstrate this
In the last passing data to child component tutorial, we built a counter in the parent component. We assigned the initial value to the counter and added increment/decrement methods. In the child Component, we used the @Input decorator to bind count property to the parent component. Whenever parent count is changed in the parent the child component is updated and displayed the count.
In this tutorial, we will move the counter to the child component. We will raise an event in the child component whenever the count is increased or decreased. We then bind to that event in the parent component and display the count in the parent component.
Download the source code for this from the GitHub from the folder inputdecorator. The The final code is available in outputdecorator folder.
Child Component
Open the child.component.ts and copy the following code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'child-component', template: `<h2>Child Component</h2> <button (click)="increment()">Increment</button> <button (click)="decrement()">decrement</button> current count is {{ count }} ` }) export class ChildComponent { @Input() count: number; @Output() countChanged: EventEmitter<number> = new EventEmitter(); increment() { this.count++; this.countChanged.emit(this.count); } decrement() { this.count--; this.countChanged.emit(this.count); } } |
Now, let us look at the code in detail
First, as usual, we need to import output & EventEmitter from @angular/core
1 2 3 | import { Component, Input, Output, EventEmitter } from '@angular/core'; |
In the inline template, we have two buttons increment and decrement. We also displaying the current count
1 2 3 4 5 6 7 8 9 10 | @Component({ selector: 'child-component', template: `<h2>Child Component</h2> <button (click)="increment()">Increment</button> <button (click)="decrement()">decrement</button> current count is {{ count }} ` }) |
In the child component, define the countChanged event of type EventEmiiter. Decorate the property with @Output decorator to make it accessible from the parent component
1 2 3 | @Output() countChanged: EventEmitter<number> = new EventEmitter(); |
Finally, we raise the event in increment & decrement methods using emit
1 2 3 4 5 6 7 8 9 10 | increment() { this.count++; this.countChanged.emit(this.count); } decrement() { this.count--; this.countChanged.emit(this.count); } |
Parent Component
In the parent component , we need to listen to the “countChanged” event
The “countChanged” event is enclosed in Parentheses. It is then assigned to the method “countChangedHandler” in the component class. The syntax is similar to Event Binding
1 2 3 | <child-component [count]=ClickCounter (countChanged)="countChangedHandler($event)"></child-component>` |
The countChangedHandler($event) method accepts the $event argument. The data associated with event is now available to in the $event property
Our CountChangedHandler is as follows. It just updates the clickCounter and also logs the count to console
1 2 3 4 5 6 | countChangedHandler(count: number) { this.ClickCounter = count; console.log(count); } |
The complete code is as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import { Component} from '@angular/core'; @Component({ selector: 'app-root', template: ` <h1>Welcome to {{title}}!</h1> <p> current count is {{ClickCounter}} </p> <child-component [count]=Counter (countChanged)="countChangedHandler($event)"></child-component>` , styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Component Interaction'; Counter = 5; countChangedHandler(count: number) { this.Counter = count; console.log(count); } } |
Run the code. Whenever the increment/decrement buttons clicked, The child raises the event. The Parent component gets notified of the this and updates the counter with the latest value.
Parent uses local variable to access the Child in Template
Parent Template can access the child component properties and methods by creating the template reference variable
Child Component
Let us update the child component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { Component} from '@angular/core'; @Component({ selector: 'child-component', template: `<h2>Child Component</h2> current count is {{ count }} ` }) export class ChildComponent { count = 0; increment() { this.count++; } decrement() { this.count--; } } |
We have removed the input, output & eventemiitter.
Our component is now have property count and two methods to increment and decrement it
Parent component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { Component} from '@angular/core'; @Component({ selector: 'app-root', template: ` <h1>{{title}}!</h1> <p> current count is {{child.count}} </p> <button (click)="child.increment()">Increment</button> <button (click)="child.decrement()">decrement</button> <child-component #child></child-component>` , styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Parent interacts with child via local variable'; } |
We have created a local variable, #child, on the tag <child-component>. The “child” is called template reference variable, which now represents the child component
The Template Reference variable is created, when you use #<varibaleName> and attach it to a DOM element. You can then, use the variable to reference the DOM element in your Template
1 2 3 | <child-component #child></child-component>` , |
Now you can use the local variable elsewhere in the template to refer to the child component methods and properties as shown below
1 2 3 4 5 | <p> current count is {{child.count}} </p> <button (click)="child.increment()">Increment</button> <button (click)="child.decrement()">decrement</button> |
The code above wires child components increment & decrement methods from the parent component
The local variable approach is simple and easy. But it is limited because the parent-child wiring must be done entirely within the parent template. The parent component itself has no access to the child.
You can’t use the local variable technique if an instance of the parent component class must read or write child component values or must call child component methods.
Parent uses a @ViewChild() to get reference to the Child Component
Injecting an instance of the child component into the parent as a @ViewChild is the another technique used by the parent to access the property and method of the child component
The @ViewChild decorator takes the name of the component/directive as its input. It is then used to decorate a property. The Angular then injects the reference of the component to the Property
For Example
In the Parent component, declare a property child which is of type ChildComponent
1 2 3 | child: ChildComponent; |
Next, decorate it with @ViewChild decorator passing it the name of the component to inject
1 2 3 | @ViewChild(ChildComponent) child: ChildComponent; |
Now, when angular creates the child component, the reference to the child component is assigned to the child property.
We now update the code from previous section
Child Component
There is no change in the child component
Parent Component
In the parent component, we need to import the viewChild Decorator. We also need to import the child component
1 2 3 4 | import { Component, ViewChild } from '@angular/core'; import { ChildComponent } from './child.component'; |
Next, create a property child which is an instance of type ChildComponent. Apply the viewChild Decorator on the child component as shown below
1 2 3 | @ViewChild(ChildComponent) child: ChildComponent; |
Finally, add increment and decrement method, which invokes the methods in the child component
1 2 3 4 5 6 7 8 9 | increment() { this.child.increment(); } decrement() { this.child.decrement(); } |
Now, the parent can access the properties and methods of child component
And in the template make necessary changes
1 2 3 4 5 6 7 | <h1>{{title}}</h1> <p> current count is {{child.count}} </p> <button (click)="increment()">Increment</button> <button (click)="decrement()">decrement</button> <child-component></child-component>` |
The complete app.component.ts is as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import { Component, ViewChild } from '@angular/core'; import { ChildComponent } from './child.component'; @Component({ selector: 'app-root', template: ` <h1>{{title}}</h1> <p> current count is {{child.count}} </p> <button (click)="increment()">Increment</button> <button (click)="decrement()">decrement</button> <child-component></child-component>` , styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Parent calls an @ViewChild()'; @ViewChild(ChildComponent) child: ChildComponent; increment() { this.child.increment(); } decrement() { this.child.decrement(); } } |
Conclusion
In this tutorial, we looked at how the parent can communicate with the child component. The Parent can subscribe to the events of the child component. It can use the Template local variable to access the properties and methods. We can also use @ViewChild decorator to inject the child component instance to the parent
In the next tutorial, we will look at the Component life cycle hooks.
Hi I am using dynamic component concept and generating multiple dynamic child components in parent component and storing dynamic component reference in ComponentRef as CompInfoComponents = new Map<string, ComponentRef>(); . Here I am unable to fetch data from dynamic child component to parent and also to validate controls present in child. Could you please help me for this??
Very good Explanation about the Component interaction
you should write a book
save text as pdf , provide github repo link
that is it
never met better explanation…
do you let me to print your tutorials for personal use only ?
bro can we do component communication for different modules
yes we can using subject .
Great!!
Excellent Article, one doubt whatever we can achieve through @Input and @Output,EventEmitter can be achieved through template reference and @Viewchild also. So, what is the exact difference between these three approaches and what are the drawbacks of each approach, in which scenario I should use @Input and @Output,EventEmitter and when template reference and when @Viewchild. Your response would be really appreciated as there are no clear explanation for the same in the web.
This was so clear and helpful! I FINALLY understand pushing data from child to parent and the event emitter stuff. Thanks!!
How can call a parent component function from child component or view?
Raise an event from child to parent using EventEmitter and then the parent can call the function
good blog but i am facing error while implement @Output — Event Emitter
count not found error shows in console.
Uncaught Error: Template parse errors:
Can’t bind to ‘count’ since it isn’t a known property of ‘app-countinparent’.
1. If ‘app-countinparent’ is an Angular component and it has ‘count’ input, then verify that it is part of this module.
2. If ‘app-countinparent’ is a Web Component then add ‘CUSTOM_ELEMENTS_SCHEMA’ to the ‘@NgModule.schemas’ of this component to suppress this message.
3. To allow any property add ‘NO_ERRORS_SCHEMA’ to the ‘@NgModule.schemas’ of this component. (”
You need to declare “app-countinparent” in the ngModule.
What an explanation.. I really loved the way ur flow
Thanks a lot for this tutorial, it saves my life this friday afternoon.
Thanks for the article. If you don’t mind, can you add ngAfterViewInit() lifecycle hook for Parent uses a @ViewChild() to get reference to the Child Component example? According to angular.io website, it says ngAfterViewInit() lifecycle hook is important when you use @ViewChild().
Thank you
Very understandable and direct to the point. Thanks a lot for this, mate. A really really big help.
Very good Article
Thank you so much. Excellent article. easy to follow and easy to understand.
Thanks Khalid
hello , good article to read briefly, can understand easily , its helps lot …..thanking you. please write some same thing like ,,,,,good ,
Thanks raja
superb