Structural Directives — @if @for @switch @defer
Structural directives change the DOM structure — adding, removing, or moving elements.
Structural directives change the DOM structure — they add, remove, or manipulate elements in the DOM.
"Structural = construction — DOM mein kuch add karo, kuch hatao." Unlike attribute directives (which just change the element's appearance), structural directives change whether the element even exists.
Angular 17+ introduced a new @ syntax for all structural directives, replacing the old *ngIf, *ngFor, and adding new ones like @switch and @defer.
All structural directives start with @ in the new syntax.
@if conditionally renders content — the element is REMOVED from DOM when false, not just hidden:
@if (isHyderabadi) {\n <p>You love biryani! 🍗</p>\n} @else {\n <p>Try our biryani, you'll love it!</p>\n}
Key behavior: When isHyderabadi is false, the first div is COMPLETELY REMOVED from the DOM (not display:none). This saves memory and keeps the DOM clean.
Chained conditions:
@if (score >= 90) { <p>Grade A</p> }\n@else if (score >= 70) { <p>Grade B</p> }\n@else { <p>Grade C</p> }
"isVisible = false se display none hota hai, @if false se DOM se hi hata deta hai."
@for loops through arrays to generate repeated content:
@for (biryani of biryanis; track biryani.id) {\n <li>{{ biryani.name }} - ₹{{ biryani.price }}</li>\n} @empty {\n <li>No biryanis found! Add some first.</li>\n}
track is REQUIRED! It helps Angular identify which items changed, moved, or were removed — like an Aadhaar card for each item:
"track = Aadhaar card — Angular ko pata chalta hai kaun sa item same hai."
What to use for track:
- ✅
track item.id— unique ID (best for objects) - ✅
track item— for primitive arrays (string, number) - ❌
track $index— only for static lists that never change order
@empty block is shown when the array is empty — no need for a separate @if check!
@switch provides cleaner multiple-condition rendering than chained @if/@else if:
@switch (orderStatus) {\n @case ('pending') {\n <span class="badge yellow">⏳ Waiting</span>\n }\n @case ('preparing') {\n <span class="badge orange">🍳 Cooking</span>\n }\n @case ('delivered') {\n <span class="badge green">✅ Delivered!</span>\n }\n @default {\n <span class="badge gray">❓ Unknown</span>\n }\n}
"Switch = menu card — ek condition, multiple options."
This is much cleaner than:
@if (status === 'pending') { ... }\n@else if (status === 'preparing') { ... }\n@else if (status === 'delivered') { ... }\n@else { ... }@defer (Angular 17+) lazily loads parts of a template — they only load when needed:
@defer (on viewport) {\n <app-heavy-chart />\n} @placeholder {\n <p>Chart will load when visible...</p>\n} @loading (minimum 500ms) {\n <app-spinner />\n} @error {\n <p>Failed to load chart</p>\n}
Triggers:
on viewport— Load when element becomes visible (scrolled into view)on interaction— Load when user clicks/tapson timer(5s)— Load after 5 secondson immediate— Load right after initial renderon idletask— Load when browser is idle
"Defer = train ka wait karna — jab zarurat ho tabhi load karo." HUGE for performance!
Key Takeaways
- ✅ @if conditionally renders content — removes elements from DOM when false.
- ✅ @for loops arrays — track is REQUIRED. Use unique IDs, not $index.
- ✅ @switch handles multiple conditions — cleaner than chained @if/@else if.
- ✅ @defer lazily loads templates on triggers like viewport, interaction, timer.
- ✅ These replace the old *ngIf, *ngFor — new @ syntax is cleaner and more powerful.
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login