Stop reading about components. Start seeing data flow. Interactive animations, live code, and hands-on demos for every concept that feels hard.
[property] = bind to @Input. Data flows from parent template to child @Input.
(event) = listen to @Output. Data flows UP from child to parent.
ngAfterViewInit.
.subscribe() to receive them..unsubscribe() to stop.<app-user-card>template: '…' for inline.ng new my-app structure.
[(ngModel)]name*ngIf adds or removes DOM elements based on a boolean — it's not just hiding them!
*ngFor loops over arrays to create repeated DOM elements. Always use trackBy for performance!
@Injectable(). It can hold data, make HTTP calls, and contain business logic.
FormBuilder is a shortcut service — it reduces boilerplate dramatically. Use it in production!
valid/invalid, touched/untouched, and dirty/pristine states. Show errors only when the user has interacted!
*ngIf="ctrl.invalid && ctrl.touched" — only show errors after user has interacted!FormArray lets you add/remove form fields dynamically — perfect for skills lists, phone numbers, addresses.
multi: true is required — it tells Angular to keep all interceptors, not replace previous ones.CommonModule to use them all.
transform() method is called every time the input changes.
async pipe is Angular's superpower — it subscribes to Observables/Promises AND automatically unsubscribes when the component is destroyed!
@Input() reference changes, it emits an event, or you call markForCheck(). Much faster!
markForCheck().
computed(), Angular tracks that dependency and re-runs when the signal changes.
count = signal(0)doubled = computed(() => count() * 2)effect(() => console.log(count()))computed() derives a new signal from other signals. It's lazy (only recalculates when read after a dependency changes) and memoized (cached until deps change).
effect() runs a side effect whenever signals it reads change. Use for logging, saving to localStorage, syncing to external systems.
untracked() if necessary.