DEV Community

Cover image for Stop Using ngIf Like This — Angular’s @if, @for & @empty Are Cleaner
Mridu Dixit
Mridu Dixit

Posted on

Stop Using ngIf Like This — Angular’s @if, @for & @empty Are Cleaner

Angular developers have used *ngIf and *ngFor for years. They work — but they also hide complexity, encourage messy templates, and become painful as UI logic grows.

Angular’s template control flow syntax (@if, @for, @empty, @switch) solves these problems with clear, explicit, and readable blocks.

If you’re still writing Angular templates the old way, this article shows why you should stop — and what to use instead.

**What’s Wrong with ngIf and ngFor?

The issue isn’t that they’re broken — it’s that they don’t scale well.

Common problems:

  • Hidden logic
  • Asterisk (*) magic that’s hard to reason about
  • Nested conditions become unreadable
  • Empty states require extra boilerplate
<div *ngIf="user; else loading">
  <app-profile [user]="user"></app-profile>
</div>

<ng-template #loading>
  <app-spinner></app-spinner>
</ng-template>

Enter fullscreen mode Exit fullscreen mode

This works — but the logic is split across multiple places.

@if — Clear, Explicit Conditional Rendering

Cleaner Alternative

@if (user) {
  <app-profile [user]="user"></app-profile>
} @else {
  <app-spinner></app-spinner>
}

Enter fullscreen mode Exit fullscreen mode

Why this is better:

  • No
  • No indirection
  • Reads like real control flow
  • Easy to extend and refactor

Nested conditions also stay readable:

@if (user) {
  @if (user.isAdmin) {
    <admin-panel />
  } @else {
    <user-dashboard />
  }
}

Enter fullscreen mode Exit fullscreen mode

*@for — A Better ngFor

Old Way

<li *ngFor="let item of items; trackBy: trackById">
  {{ item.name }}
</li>

Enter fullscreen mode Exit fullscreen mode

New Way

@for (item of items; track item.id) {
  <li>{{ item.name }}</li>
}

Enter fullscreen mode Exit fullscreen mode

Built-in variables are explicit and intuitive:

@for (item of items; let i = $index) {
  <p>{{ i + 1 }}. {{ item.name }}</p>
}

Enter fullscreen mode Exit fullscreen mode

Available variables:

  • $index
  • $count
  • $first
  • $last
  • $even
  • $odd

@empty — No More Manual Empty State Checks

This is where Angular really shines.

Old Pattern

<ul *ngIf="items.length > 0; else empty">
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

<ng-template #empty>
  No items found
</ng-template>

Enter fullscreen mode Exit fullscreen mode

New Pattern

@for (item of items) {
  <li>{{ item }}</li>
} @empty {
  <li>No items found</li>
}

Enter fullscreen mode Exit fullscreen mode

Why @empty is a big win:

  • No extra conditions
  • Empty state stays next to the list
  • Perfect for tables, dropdowns, dashboards

@switch — Readable State-Based UI

Old ngSwitch

<div [ngSwitch]="status">
  <p *ngSwitchCase="'loading'">Loading...</p>
  <p *ngSwitchCase="'success'">Success</p>
  <p *ngSwitchDefault>Error</p>
</div>

Enter fullscreen mode Exit fullscreen mode

New Control Flow

@switch (status) {
  @case ('loading') {
    <p>Loading...</p>
  }
  @case ('success') {
    <p>Success</p>
  }
  @default {
    <p>Error</p>
  }
}

Enter fullscreen mode Exit fullscreen mode

This reads exactly how it behaves.

Works Perfectly with Signals

items = signal<string[]>([]);

Enter fullscreen mode Exit fullscreen mode
@for (item of items()) {
  <p>{{ item }}</p>
} @empty {
  <p>No data available</p>
}

Enter fullscreen mode Exit fullscreen mode

No subscriptions.
No async pipe noise.
Angular handles reactivity automatically.

Performance & Maintainability Benefits

Angular’s control flow blocks:

  • Reduce unnecessary DOM nodes
  • Improve compile-time optimizations
  • Work seamlessly with zoneless Angular
  • Make templates easier to test and review This is not just syntax sugar — it’s better architecture.

*Should You Stop Using ngIf Completely?

No — existing code is fine.

But for:

  • New components
  • New features
  • Signal-based state
  • Complex UI logic

👉 @if, @for, and @empty should be your default choice

Final Thoughts

*ngIf and *ngFor were great — but Angular templates have moved on.

If you care about:

  • clean templates
  • readable UI logic
  • scalable Angular apps

then it’s time to stop using *ngIf like it’s 2018 and start writing templates the modern Angular way.

Top comments (0)