Methods to Share Data Between Angular Components
Estimated study time: 9 minutes. Choosing the right data-sharing pattern for parent, child, and sibling components.
As an Angular app grows, components need to communicate. Angular offers several patterns, and choosing the right one depends on the relationship between the components involved.
1. @Input() — Parent to Child
// parent.component.html
<app-child [userName]="name"></app-child>
// child.component.ts
@Input() userName!: string;
2. @Output() and EventEmitter — Child to Parent
// child.component.ts
@Output() itemSelected = new EventEmitter<string>();
selectItem(item: string) { this.itemSelected.emit(item); }
// parent.component.html
<app-child (itemSelected)="onItemSelected($event)"></app-child>
3. Shared Service — Any to Any
For components that aren't directly related (siblings, or components far apart in the tree), an injectable service with a shared observable is the standard pattern.
@Injectable({ providedIn: 'root' })
export class DataService {
private messageSource = new BehaviorSubject<string>('default');
currentMessage$ = this.messageSource.asObservable();
updateMessage(msg: string) { this.messageSource.next(msg); }
}
4. @ViewChild — Direct Access to a Child
Lets a parent directly call methods or read properties on a child component instance, useful for imperative actions like triggering an animation or form reset.
5. State Management Libraries
For large applications with deeply nested or complex shared state, libraries like NgRx or Akita centralize state in a predictable, testable store rather than passing data through many component layers.
Choosing the Right Approach
| Relationship | Recommended Approach |
|---|---|
| Parent → Child | @Input() |
| Child → Parent | @Output() + EventEmitter |
| Siblings / unrelated | Shared service with Observable |
| Complex, app-wide state | NgRx / Akita |