Sharing data between components in Angular is one of the most important part to understand. We are going to learn how to pass data from one component to another component using @Input, @Output and EventEmitter in Angular app.
Let’s discuss different methods of sharing data in any angular application. We will focus on these methods:
@Input
: sharing data from parent to child
@ViewChild
: sharing data from child to parent
@Output & EventEmitter
: sharing data from child to parent
This is the most common method of sharing data in Angular application. We will use @Input() decorator to pass data. Create a parent component named app-parent
in your app folder. Use this command to generate the component:
Creating parent component
1
2
3
4
5
|
CREATE src/app/parent/parent.component.css (0 bytes)
CREATE src/app/parent/parent.component.html (25 bytes)
CREATE src/app/parent/parent.component.spec.ts (628 bytes)
CREATE src/app/parent/parent.component.ts (269 bytes)
UPDATE src/app/app.module.ts (683 bytes)
|
parent.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
|
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-parent",
templateUrl: "./parent.component.html",
styleUrls: ["./parent.component.css"],
})
export class ParentComponent implements OnInit {
constructor() {}
ngOnInit() {}
}
|
Now, let’s create child component named app-child
using this command in your app folder.
Creating child component
child.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
|
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-child",
templateUrl: "./child.component.html",
styleUrls: ["./child.component.css"],
})
export class ChildComponent implements OnInit {
constructor() {}
ngOnInit() {}
}
|
Till now, we have just created our parent and child components in our app. Let' see how to pass data between them. Import the Input
decorator in line 1 of child.component.ts
file.
1
|
import { Component, OnInit, Input } from "@angular/core";
|
Add appChildMessage
property with @Input()
decorator in same file.
1
|
@Input() appChildMessage: string;
|
Add this line to child.component.html
file.
1
2
3
4
|
<p>
child works!
</p>
<p>Message from parent: {{appChildMessage}}</p>
|
Now, let’s add these lines to parent component.
parent.component.ts
1
|
appParentMessage = "This message is from parent";
|
parent.component.html
1
2
3
4
|
<p>
parent works!
</p>
<app-child [appChildMessage]="appParentMessage"></app-child>
|
So, the complete code would be like this.
parent.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-parent",
templateUrl: "./parent.component.html",
styleUrls: ["./parent.component.css"],
})
export class ParentComponent implements OnInit {
constructor() {}
ngOnInit() {}
appParentMessage = "This message is from parent";
}
|
parent.component.html
1
2
3
4
|
<p>
parent works!
</p>
<app-child [appChildMessage]="appParentMessage"></app-child>
|
child.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import { Component, OnInit, Input } from "@angular/core";
@Component({
selector: "app-child",
templateUrl: "./child.component.html",
styleUrls: ["./child.component.css"],
})
export class ChildComponent implements OnInit {
constructor() {}
ngOnInit() {}
@Input() appChildMessage: string;
}
|
child.component.html
1
2
3
4
|
<p>
child works!
</p>
<p>Message from parent: {{appChildMessage}}</p>
|
Method 2: Child to Parent using @ViewChild()
Using @ViewChild() decorator, we can inject one component to another, giving the parent access to its attributes and functions.
Note: Child won’t be available until after the view has been initialized. So, we need to implement the AfterViewInit lifecycle hook to receive the data from the child.
Let’s look at our parent component code. Write these lines in parent component.
parent.component.ts
1
2
|
import { Component, ViewChild, AfterViewInit } from "@angular/core";
import { ChildComponent } from "../child/child.component";
|
Implement the AfterViewInit
in component class.
1
|
export class ParentComponent implements AfterViewInit
|
Add these lines in component class file.
1
2
3
4
5
6
|
@ViewChild(ChildComponent) child;
appParentMessage: string;
ngAfterViewInit() {
this.appParentMessage = this.child.appChildMessage;
}
|
Let’s look at complete code.
parent.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import { Component, ViewChild, AfterViewInit } from "@angular/core";
import { ChildComponent } from "../child/child.component";
@Component({
selector: "app-parent",
templateUrl: "./parent.component.html",
styleUrls: ["./parent.component.css"],
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child;
appParentMessage: string;
constructor() {}
ngAfterViewInit() {
this.appParentMessage = this.child.appChildMessage;
}
}
|
parent.component.html
1
2
3
4
5
|
<p>
parent works!
</p>
Child Message: {{ appParentMessage }}
<app-child></app-child>
|
child.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import { Component, OnInit, Input } from "@angular/core";
@Component({
selector: "app-child",
templateUrl: "./child.component.html",
styleUrls: ["./child.component.css"],
})
export class ChildComponent implements OnInit {
constructor() {}
ngOnInit() {}
appChildMessage = "This message is from child to parent";
}
|
Method 3: Child to Parent using @Output
and EventEmitter
In this method, child component will emit the data, which will be listen by parent component. This ideal condition for this approach is when you want to share some data on some events like button clicks, users and other form related events.
Use this link to read more about @Output and EventEmitter.
We are going to create a function in the parent to receive the message and set it equal to the message variable. Also,Β we are going to declare a messageEvent
variable with the Output
decorator and set it equal to a new event emitter. Then we will have a function named sendMessage
that calls emit on this event with the message we want to send. At the end, we will create a button to trigger this function.
Let’s look at complete code.
parent.compoent.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import { Component } from "@angular/core";
@Component({
selector: "app-parent",
templateUrl: "./parent.component.html",
styleUrls: ["./parent.component.css"],
})
export class ParentComponent {
constructor() {}
appParentMessage: string;
receiveMessage($event) {
this.appParentMessage = $event;
}
}
|
parent.component.html
1
2
3
4
5
|
<p>
parent works!
</p>
Message: {{appParentMessage}}
<app-child (messageEvent)="receiveMessage($event)"></app-child>
|
child.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent {
constructor() { }
message: string = "I am calling from Child Component!"
@Output() messageEvent = new EventEmitter<string>();
sendMessage() {
this.messageEvent.emit(this.message)
}
|
child.component.html
1
2
3
4
|
<p>
child works!
</p>
<button (click)="sendMessage()">Send Message</button>
|
Summary
In our post, we have learned about how to share data between parent and child components using @Input(), @Output and EventEmitter. Data sharing is very important concept, and everybody needs to share data between application’s components.
Further reading