
- Angular Tutorial
- Angular - Home
- Angular - Overview
- Angular - Features
- Angular - Advantages & Disadvantages
- Angular Basics
- Angular - Environment setup
- Angular - First Application
- Angular - MVC Architecture
- Angular Components
- Angular - Components
- Angular - Component Lifecycle
- Angular - View Encapsulation
- Angular - Component Interaction
- Angular - Component Styles
- Angular - Nested Components
- Angular - Content projection
- Angular - Dynamic components
- Angular - Elements
- Angular Templates
- Angular - Templates
- Angular - Template statements
- Angular - Template Variables
- Angular - SVG as Templates
- Angular Binding
- Angular - Data Binding
- Angular - Interpolation
- Angular - Event Binding
- Angular - Property Binding
- Angular - Attribute Binding
- Angular - Class Binding
- Angular - Style Binding
- Angular - Two-way Binding
- Angular Directives
- Angular - Directives
- Angular - Attribute Directives
- Angular - Structural Directives
- Angular - Custom Directives
- Angular Pipes
- Angular - Pipes
- Angular - Built-in Pipes
- Angular - Custom Pipes
- Angular Forms
- Angular - Forms
- Angular - Template Driven Forms
- Angular - Reactive Forms
- Angular - Form Validation
- Angular - Dynamic Forms
- Angular Dependency Injection
- Angular - Dependency Injection
- Angular - Injectable Service
- Angular Routing
- Angular - Routing
- Angular - Dynamic Routes
- Angular - Wildcard Routes
- Angular - Nested Routes
- Angular - Navigation
- Angular - Routing in SPA
- Angular - Custom Route Matches
- Angular - Router Reference
- Angular HTTP Client programming
- Angular - Services
- Angular - HTTP Client
- Angular - Request
- Angular - Response
- Angular - GET
- Angular - POST
- Angular - PUT
- Angular - DELETE
- Angular - JSONP
- Angular - CRUD Operations Using HTTP
- Angular Modules
- Angular - Introduction to Modules
- Angular - Root Module
- Angular - Feature Module
- Angular - Sharing Module
- Angular - Routing Module
- Angular - NgModules
- Angular Animation
- Angular - Animations
- Angular Service Workers & PWA
- Angular - Service Workers & PWA
- Angular Testing
- Angular - Testing Overview
- Angular Design Patterns
- Angular - Design Patterns
- Angular - Lazy Loading
- Angular - Singleton Pattern
- Angular - Observer Pattern
- Angular Libraries
- Angular - Libraries
- Angular - Angular Material
- Angular - PrimeNG
- Angular - RxJS
- Angular Advanced
- Angular - Signals
- Angular - Authentication & Authorization
- Angular - Internationalization
- Angular - Standalone Component
- Angular - Accessibility
- Angular - Web Workers
- Angular - Server Side Rendering
- Angular - Ivy Compiler
- Angular - Building with Bazel
- Angular - Backward Compatibility
- Angular - Reactive Programming
- Angular Tools
- Angular - CLI
- Angular Material UI Elements
- Angular - Paginator
- Angular - Datepicker
- Angular - Select Drop-down
- Angular Miscellaneous
- Angular - Third Party Controls
- Angular - Configuration
- Angular - Displaying Data
- Angular - Decorators & Metadata
- Angular - Basic Example
- Angular - Error Handling
- Angular - Testing & Building a Project
- Angular - Lifecycle Hooks
- Angular - User Input
- Angular - What's New?
- Angular Useful Resources
- Angular - Quick Guide
- Angular - Useful Resources
- Angular - Discussion
Angular - Component Interaction
Sharing Data between Angular Components
Angular provides options to share data from parent component to child component as well as, child to parent component. Also, it is possible to share data between any other component within the Angular application. Component is a TypeScript class decorated with the @Component decorator. It is used to create the user interface.
Data sharing is the practice of making important information accessible to different parts of an application. It is done by transferring data from one component to another, allowing access to data during operations, or synchronizing data between different parts of an application.
Interaction between components is one of the important and necessary features in the context of component based architecture. Angular provides multiple options to pass and receive data between components. Let us see how to share data between components in this tutorial.
How Components Interact in Angular?
In Angular, parent and child components shares data or interacts to each other through the following ways −
- Using @Input decorator
- Using @Output decorator
- Using local variable
- Using @Viewchild decorator
- Using Services
Using @Input Decorator
The parent component can pass the data to the child component through the @Input()decorator. The child component receives data during its entire life cycle from initialization to destruction. Angular is designed in such a way that the child component automatically intercepts the data changes from the parent component and does the necessary update. Angular also provides hooks to intercept the data changes and write custom processing.
Overall, we have three ways for the child component to intercept data from parent component −
- Auto interception
- Setter interception
- ngOnChanges hook
Auto Interception
Auto interception simplifies receiving the data from parent component. Angular provides a decorator @Input to receive data from parent component. It receives the data whenever the parent component updates the data Configuring Input decorator is very simple. Just append the input decorator to a property in the child component and then pass the data from parent component through child component attributes in the template.
Example
Let us create a child component and then try to pass the data from parent to child and render it in the child component.
Step 1: Create a new child component, InOutChildSample using angular CLI as shown below −
$ ng generate component InOutChildSample CREATE src/app/in-out-child-sample/in-out-child-sample.component.html (35 bytes) CREATE src/app/in-out-child-sample/in-out-child-sample.component.spec.ts (688 bytes) CREATE src/app/in-out-child-sample/in-out-child-sample.component.ts (295 bytes) CREATE src/app/in-out-child-sample/in-out-child-sample.component.css (0 bytes)
Step 2: Add a counter property in the child component and decorate it with @Input() decorator as shown below −
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-in-out-child-sample', templateUrl: './in-out-child-sample.component.html', styleUrls: ['./in-out-child-sample.component.css'] }) export class InOutChildSampleComponent { @Input() counter : number = 0; }
Step 3: Open the child component template, in-out-child-sample.component.html and use the counter property as shown below −
<div> <p>Counter: {{counter}}</p> </div>
Step 4: Open the parent component template, app.component.html and render the child component along with counter attribute as shown below −
<app-in-out-child-sample [counter]="counter"></app-in-out-child-sample> <router-outlet />
Step 5: Open the app.component.ts file and add the code given below −
import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { InOutChildSampleComponent } from './in-out-child-sample/in-out-child-sample.component'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, InOutChildSampleComponent], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = 'sample-app'; counter = 10; }
Step 6: Finally, run the application and check that the counter shows whether the value passed from the parent component or not −

Setter Interception
The setter based interception is just an extension of the previous technique. It basically uses a getter and setter for the property used in @Input decorator.
Example
Let us change our counter example, in-out-child-sample.component.ts to intercept the counter using setter and reset the counter to 1, if the counter value exceeds 25.
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-in-out-child-sample', standalone: true, imports: [InOutChildSampleComponent], templateUrl: './in-out-child-sample.component.html', styleUrl: './in-out-child-sample.component.css' }) export class InOutChildSampleComponent { @Input() get counter(): number { return this._counter; } set counter(val: number) { this._counter = val || 0; if(val > 25) this._counter = val % 25; } private _counter: number = 1; }
Add a function to increment the counter value in the parent component as shown below −
inc() { this.counter++ }
Add a button in the parent components template and bind the function as shown below −
<button (click)="inc()">Increment counter</button> <app-in-out-child-sample [counter]="counter" />
Run the application, and you can see that the counter will reset to 1 once it reaches 25.

The ngOnChanges Hook Interception
As we learned in the life cycle of a component and its hook methods, ngOnChanges is a hook method, which will run whenever angular detects changes in its input.
ngOnChanges hook accepts an object of type SimpleChanges. SimpleChanges is a dictionary having all properties with changes. We can go through all the properties and find the latest value of the property. The pseudo-code to go through all changed properties is as follows −
ngOnChanges(changes: SimpleChanges) { for (const key in changes) { const prop = changes[key]; const prevVal = prop.previousValue const currentVal = prop.currentValue cont isFirstChange = pop.isFirstChange() if (prop.isFirstChange()) { console.log("The current value is ${prop.currentValue}") } else { console.log(`${key} changed from ${prop.previousValue} to ${prop.currentValue}`); } } }
Using @Output Decorator
Child component can send the data to parent component through the @Output decorator. Use of this decorator is quite simple and similar to @Input decorator except that the output is actually an event emitter passing the data (output) along with event. The parent component can be subscribed for the event in the child component and get the emitted value from the child component whenever the data is changed in the child component.
Example
Let us write an @output decorator in our child component, InOutChildSample component and try to get the output from the parent component.
Step 1: Create an output event emitter in the child component, in-out-child-sample.component.ts along with a method to pass the value of the counter by emitting the event along with counter data in the child component, in-out-child-sample.component.ts.
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-in-out-child-sample', standalone: true, imports: [InOutChildSampleComponent], templateUrl: './in-out-child-sample.component.html', styleUrl: './in-out-child-sample.component.css' }) export class InOutChildSampleComponent { @Input() counter : number = 0; @Output() counterEvent = new EventEmitter<number>(); passCounterToParent() { this.counterEvent.emit(this.counter) } }
Step 2: Open the child component template, in-out-child-sample.component.html and add a button to invoke the counter event when the user clicks the button.
<div> <p>Counter: {{counter}}</p> <button (click)="passCounterToParent()">Pass Counter to Parent</button> </div>
Here,
click is the button click event and it is configured to run passCounterToParent() function when it is clicked.
Step 3: Add a variable in the parent component to hold the output data passed through event from child component. Also, add a function in the parent component to get the output data passed through event from child component.
import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { InOutChildSampleComponent } from './in-out-child-sample/in-out-child-sample.component'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, InOutChildSampleComponent], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = 'sample-app'; counter = 10; childCounter: number = 0; inc() { this.counter++ } get(val: number) { this.childCounter = val; } }
Step 4: Open the parent component template, app.component.html and add the code as shown below −
<button (click)="inc()">Increment counter</button> <p>Data from child: {{childCounter}}</p> <app-in-out-child-sample [counter]="counter" (counterEvent)="get($event)" />
Here,
counterEvent is the event from the child component
get($event) is the callback function. $event will hold the current counter value.
childContent is the data from the child component.
Step 5: Finally, run the application and you can see that the child component will send the updated counter value to the parent component when the button in the child component is clicked.

Using Local Variable
Parent components can get complete access to the child component throughlocal variable. However, parent component gets access to the child component in its template only.
Example
Let us create two component, ParentCounterComponent and ChildCounterComponent to understand the concept. The purpose of the ParentCounterComponent is to provide counter functionality through two button, increment and decrement button. The increment button will increment the counter and the decrement button will decrement the counter. Parent component will get the increment and decrement functionality from child component instead of implementing itself.
Step 1: Create child component, ChildCounterComponent using angular CLI as shown below −
ng generate component ChildCounter CREATE src/app/child-counter/child-counter.component.html (29 bytes) CREATE src/app/child-counter/child-counter.component.spec.ts (658 bytes) CREATE src/app/child-counter/child-counter.component.ts (273 bytes) CREATE src/app/child-counter/child-counter.component.css (0 bytes)
Step 2: Declare a variable counter and two methods inc() and dec() to increment and decrement the counter respectively inside the child component −
import { Component } from '@angular/core'; @Component({ selector: 'app-child-counter', standalone: true, imports: [], templateUrl: './child-counter.component.html', styleUrl: './child-counter.component.css' }) export class ChildCounterComponent { counter: number = 0 // increment and decrement counter inc() { this.counter++ } dec() { this.counter-- } }
Step 3: Next, open parent component's template file, app.component.html and add child component along with an id, #child to access the child component.
<app-child-counter #child></app-child-counter>
Step 4: Next, add two buttons and bind click events with child component's inc() and dec() methods accessed through child identifier. Also, show the current value of counter using child identifier.
<p>counter: {{child.counter}}</p> <button (click)="child.inc()">Increment</button> <button (click)="child.dec()">Decrement</button> <app-child-counter #child></app-child-counter> <router-outlet />
Step 5: Next, include the given code inside app.component.ts file.
import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { ChildCounterComponent } from './child-counter/child-counter.component'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, ChildCounterComponent], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = 'exampleApp'; }
Step 6: Finally, run the application and check whether the counter is working fine.

Using @Viewchild Decorator
Like the local variable, the @ViewChild decorator is also used to get complete access to the child component. However, along with template, the parent component will get access to the child component in its class environment as well. This makes a huge difference as the parent component can use the child component functionality in its methods as well.
Example
To understand the @Viewchild decorator, let's change the parent component, i.e. AppComponent. Now, we will use @ViewChild concept instead of local variable. We don't need to make any changes in the child component.
Step 1: Import necessary classes from @angular/core module:
import { Component, ViewChild, AfterViewInit } from '@angular/core';
Step 2: Implement AfterViewInit life cycle hook as shown below:
export class VcParentCounterComponent implements AfterViewInit { ngAfterViewInit() { // ... } }
Step 3: Access the child component using @ViewChild as shown below −
@ViewChild(ChildCounterComponent) private child! : ChildCounterComponent;
Here, @ViewChild decorator accepts the type of the child component, which is in the component's template.
Step 4: Implement increment and decrement functionality by accessing the child component.
inc() { this.child.inc() } dec() { this.child.dec() }
Here, we have used this.child variable to access the functionality from child component.
Step 5: Implement a counter functionality to retrieve the current counter value as shown below −
counter() { return 0; } ngAfterViewInit() { setTimeout(() => this.counter = () => this.child.counter, 0) }
Here, we have created a counter method in ngAterViewInit life cycle hook. The child component will be available only after this life cycle. So, we have created a dummy counter method (which needs to access child component's counter value ) during component initialization and the update the counter method in the hook method.
Step 6: The complete code of the AppComponent is as follows −
import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { ChildCounterComponent } from './child-counter/child-counter.component'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, ChildCounterComponent], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent implements AfterViewInit { title = 'exampleApp'; @ViewChild(ChildCounterComponent) private child! : ChildCounterComponent; inc() { this.child.inc() } dec() { this.child.dec() } counter() { return 0; } ngAfterViewInit() { setTimeout(() => this.counter = () => this.child.counter, 0) } }
Step 7: Next, open the component's template file, app.component.html and add the child component along with button and method binding as shown below −
<p>counter: {{ counter() }}</p> <button (click)="inc()">Increment</button> <button (click)="dec()">Decrement</button> <app-child-counter></app-child-counter>
Here, we have not included the identifier and used only the parent components functionality instead of child component (which we have done in previous example, local variable concept). The parent component will get the required functionality from child variable, which it got through @ViewChild decorator.
Step 8: Finally, run the application and check that the counter shows that the value passed from parent component as shown below −

Using a Common Service
Service is an integral part of the angular framework. We can create a service to implement specific functionality and then use it in any component. The best use cases of services are as follows:
- API calls
- Utility functions
- Sharing data between components
Example
Let us learn how to use services to share data between components in this section. We will learn the step by step process to share data through a service in this example.
Step 1: Create a service, MyCounterService using angular CLI as shown below −
ng g service services/MyCounter CREATE src/app/services/my-counter.service.spec.ts (389 bytes) CREATE src/app/services/my-counter.service.ts (147 bytes)
It is better to put all the services inside a single folder. Therefore, we are creating MyCounter inside service folder using the above command.
Step 2: Create a component, MyCounterServiceComponent using angular CLI as shown below −
ng generate component MyCounterService CREATE src/app/my-counter-service/my-counter-service.component.html (34 bytes) CREATE src/app/my-counter-service/my-counter-service.component.spec.ts (687 bytes) CREATE src/app/my-counter-service/my-counter-service.component.ts (292 bytes) CREATE src/app/my-counter-service/my-counter-service.component.css (0 bytes)
Step 3: Create an observable object to track the value of counter variable in the service as shown below −
private counterSource = new Subject<number>(); public counter$ = this.counterSource.asObservable()
Here,
counterSource is a variable of type Subject. Subject is an observable object provided by rxjs library. Subject can emit and receive values.
Invoked asObservable method on the counterSource to hide the identity of the source sequence.
Step 4: Implement increment and decrement methods as shown below −
inc(val: number) { this.counterSource.next(val + 1) } dec(val: number) { this.counterSource.next(val - 1) }
Here,
next() method from counterSource is used to update the value of the counter.
Step5: The complete code of the service, MyCounterService is as follows:
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class MyCounterService { constructor() { } private counterSource = new Subject<number>(); public counter$ = this.counterSource.asObservable() inc(val: number) { this.counterSource.next(val + 1) } dec(val: number) { this.counterSource.next(val - 1) } }
Step 6: Now, open the my-counter-service.component.ts file and inject the service through constructor in the component.
export class MyCounterServiceComponent { constructor(private counterService: MyCounterService) { } }
Step 7: Subscribe to the observables available in the service through component constructor as shown below −
this.counterService.counter$.subscribe( counter => { this.counter = counter; })
Here, the subscription will update the counter value whenever there is a change in the observable.
Step 8: Implement increment (inc()) and decrement (dec()) methods by calling counter service methods as shown below −
inc() { this.counterService.inc(this.counter) } dec() { this.counterService.dec(this.counter) }
Step 9: The complete code of the component, MyCounterServiceComponent is as follows,
import { Component } from '@angular/core'; import { MyCounterService } from '../my-counter.service' @Component({ selector: 'app-my-counter-service', templateUrl: './my-counter-service.component.html', styleUrls: ['./my-counter-service.component.css'], }) export class MyCounterServiceComponent { counter: number = 0; constructor(private counterService: MyCounterService) { this.counterService.counter$.subscribe( counter => { this.counter = counter; }) } inc() { this.counterService.inc(this.counter) } dec() { this.counterService.dec(this.counter) } }
Step 10: Next, open the component's template, my-counter-service.component.html and write template markup to show the current counter value and then add two more buttons to increment and decrement the counter value. Bind inc() and dec() methods to increment and decrement button's click event respectively.
<p>counter: {{counter}}</p> <button (click)="inc()">Increment</button> <button (click)="dec()">Decrement</button>
Step 11: Next, open the app component's template and include our component as shown below −
<app-my-counter-service /> <router-outlet />
Step 12: Run the application and check the output.

Step 13: Next, add another component in the app component's template as shown below −
<app-my-counter-service /> <app-my-counter-service /> <router-outlet></router-outlet>
Step14: Run the application and see that incrementing one component will reflect in the other component as well. It happens as it is based on the same service.

Multiple Choice Questions on Angular Component Interaction
Now that you have learned the how Angular Components interacts, let's test your knowledge. Please answer the following questions based on your understanding −
Q. 1 - Which Angular decorator is used to pass data from a parent component to a child component?
Answer : C
Explanation
The @Input decorator bind data of the parent component to a property in the child component.
Q. 2 - Which lifecycle hook detect changes in input properties in Angular?
Answer : A
Explanation
The ngOnChanges lifecycle hook is called whenever Angular detects changes in the input properties of a component.
Q. 3 - Use of @Output decorator:
A - It allows the parent component to pass data to the child component.
B - It creates an event emitter for the child to send data to the parent.
Answer : B
Explanation
The @Output decorator is used to emit events from the child component to the parent component.