Mastering Data Flow: Beyond the Basics
Angular's architecture relies heavily on a strict hierarchy of components. Understanding how to move data efficiently between these components is the difference between a spaghetti-code application and a scalable enterprise solution. While @Input and @Output are the bread and butter, nuances exist that every developer must master.
Unidirectional Data Flow
Angular enforces unidirectional data flow. Data flowsdown from parent to child via property bindings, and events flowup from child to parent via event bindings. This predictability makes debugging significantly easier because you always know where data is coming from.
Intercepting Inputs: ngOnChanges vs. Setters
Often, you need to react when an input value changes. You have two main options:
ngOnChanges()lifecycle hook: Best when you need to watch multiple inputs simultaneously or need the previous value of the input.- TypeScript Setters: Best for reacting to a specific input change in isolation.
// Using a Setter for interception
private _amount: number;
@Input()
set amount(value: number) {
this._amount = value < 0 ? 0 : value; // Validation logic
}
get amount(): number { return this._amount; }Alternative Patterns: ViewChild & Services
@ViewChild()
Allows a parent to access public methods and properties of a child directly. Useful for controlling child logic (e.g., `child.resetForm()`), but tightly couples components.
Shared Services
For components that are siblings or far apart in the tree. Uses RxJS `BehaviorSubject` to hold state. The "Angular Way" for global state.
Pro Tip: Avoid "Input Drilling" (passing data through 5 layers of components just to reach the bottom). If you pass data down more than 2-3 layers, consider using a Shared Service or a state management library like NgRx or Signals.