Note: This article is published on 02/08/2025.
This series of articles will discuss the major feafures for Angular. The way to discuss could be AI in concept + Code Demo in StackBlitz | Instant Dev
Advanced:
Note (after writing this article):
Since the concept of component interaction here is with similar or same mechanizm or funcationality as view variable transfer data between MVC controllers, saytherefore, I put the other article series of View Variables in ASP.NET MVC here as references:
A - Introduction
Angular is a component based platform and all components make up the application. The major mechanizim for Angular is the data trasferting, either within a component or between (among) components. This article will discuss the data transfer between different Angular components.
The content of this article:
- Parent to Child (Using @Input())
- Child to Parent (Using
@Output()
and EventEmitter
)
- Sibling Components (Using a Shared Service)
- Parent Accessing Child with
@ViewChild()
- Using Local Storage / Session Storage
- Route Parameters (Passing Data via URL)
- Query Parameters
- Router State Transfer
- Using NgRx for Global State Management
- Angular Signals (Angular 16+)
In Angular, data transfer between components can be achieved in several ways, depending on the relationship between the components and the nature of the data. Here are the main approaches:
1. Parent to Child (Using @Input())
Use @Input()
decorator to pass data from a parent component to a child component.
Parent Component (HTML):
<app-child [message]="parentMessage"></app-child>
Parent Component (TypeScript):
export class ParentComponent {
parentMessage = 'Hello from Parent!';
}
Child Component (TypeScript):
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `<p>{{ message }}</p>`,
})
export class ChildComponent {
@Input() message!: string;
}
Note: Detailed example, please see this: Angular Features (2-1) --- Component Interaction (1) by @Input/@Output
✅ Best for: Passing static data or objects from parent to child.
2. Child to Parent (Using @Output()
and EventEmitter
)
Use @Output()
and EventEmitter
to send data from child to parent.
Child Component (TypeScript)
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `<button (click)="sendMessage()">Send Data</button>`,
})
export class ChildComponent {
@Output() messageEvent = new EventEmitter<string>();
sendMessage() {
this.messageEvent.emit('Hello from Child!');
}
}
Parent Component (HTML)
<app-child (messageEvent)="receiveMessage($event)"></app-child>
<p>Received: {{ childMessage }}</p>
Parent Component (TypeScript)
export class ParentComponent {
childMessage = '';
receiveMessage(message: string) {
this.childMessage = message;
}
}
Note: Detailed example, please see this: Angular Features (2-1) --- Component Interaction (1) by @Input/@Output
✅ Best for: When a child component needs to send events or data to its parent.
3. Sibling Components (Using a Shared Service)
Use a shared service with RxJS Subject or BehaviorSubject to enable communication between sibling components.
Shared Service (data.service.ts)
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class DataService {
private messageSource = new BehaviorSubject<string>('Initial Message');
currentMessage = this.messageSource.asObservable();
changeMessage(message: string) {
this.messageSource.next(message);
}
}
Component A (Sending Data)
import { Component } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-component-a',
template: `<button (click)="sendMessage()">Send Message</button>`,
})
export class ComponentA {
constructor(private dataService: DataService) {}
sendMessage() {
this.dataService.changeMessage('Message from Component A');
}
}
Component B (Receiving Data)
import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-component-b',
template: `<p>{{ message }}</p>`,
})
export class ComponentB implements OnInit {
message!: string;
constructor(private dataService: DataService) {}
ngOnInit() {
this.dataService.currentMessage.subscribe(msg => this.message = msg);
}
}
✅ Best for: Sharing data between sibling components.
4. Parent Accessing Child with @ViewChild()
Use @ViewChild()
in a parent component to directly access the child component’s methods or properties.
Child Component
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: `<p>Child Component</p>`,
})
export class ChildComponent {
getMessage() {
return 'Message from Child';
}
}
Parent Component
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from '../child/child.component';
@Component({
selector: 'app-parent',
template: `<app-child></app-child> <button (click)="accessChild()">Get Message</button>`,
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child!: ChildComponent;
ngAfterViewInit() {
console.log(this.child.getMessage());
}
accessChild() {
alert(this.child.getMessage());
}
}
✅ Best for: When the parent needs to directly interact with the child component.
5. Using Local Storage / Session Storage
For persisting data across components and page reloads, use localStorage
or sessionStorage
.
Saving Data
localStorage.setItem('key', JSON.stringify({ name: 'Angular' }));
Retrieving Data
const data = JSON.parse(localStorage.getItem('key') || '{}');
console.log(data.name);
✅ Best for: Storing temporary data that persists across page refreshes.
6. Route Parameters (Passing Data via URL)
Use Angular Router to pass data via route parameters.
Routing Module
{ path: 'details/:id', component: DetailsComponent }
Navigating with Data
this.router.navigate(['/details', item.id]);
Accessing Data in Component
import { ActivatedRoute } from '@angular/router';
constructor(private route: ActivatedRoute) {}
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
}
✅ Best for: Passing dynamic values through the URL.
7. Query Parameters
Instead of route parameters, use query parameters.
Navigating with Query Params
this.router.navigate(['/details'], { queryParams: { name: 'Angular' } });
Accessing Query Params
this.route.queryParams.subscribe((params) => {
console.log(params['name']);
});
✅ Best for: Sending optional parameters via the URL.
8. Router State Transfer
Pass data without exposing it in the URL.
Navigating with State
this.router.navigate(['/details'], { state: { data: myData } });
Retrieving Data
const receivedData = this.router.getCurrentNavigation()?.extras.state?.data;
✅ Best for: Transferring temporary data securely.
9. Using NgRx for Global State Management
For complex applications, NgRx provides a centralized state management solution.
Example
this.store.dispatch(setData({ payload: 'New Data' }));
this.store.select(selectData).subscribe(data => console.log(data));
✅ Best for: Large-scale applications that require state management.
10. Angular Signals (Angular 16+)
If using Angular 16+, leverage signals for reactive state management.
import { signal } from '@angular/core';
export class MyComponent {
data = signal<string>('Initial Value');
updateData() {
this.data.set('Updated Value');
}
}
✅ Best for: Modern, reactive state management.
Choosing the Right Method
- Parent → Child:
@Input()
- Child → Parent:
@Output()
- Sibling Components: Shared Service with
Subject
- Persisting Data:
localStorage
/ sessionStorage
- Across Routes: Route Parameters, Query Params, or Router State
- Global State: NgRx or Angular Signals
Let me know if you need more details! 🚀
Summary Table
![]()
References:
- ChatGPT: ways to transfer data in angular