Control Flow Baru — Angular

Angular 17+ memperkenalkan built-in control flow yang lebih bersih. @if @if (loggedIn) { Selamat datang! } @else { Silakan login } @for @for (item of items…

Control flow adalah blok di template yang memutuskan bagian mana yang dirender: @if memilih ditampilkan atau gak, @for mengulang satu bagian untuk tiap isi array, dan @switch memilih satu dari beberapa kemungkinan. Bayangin papan menu Martabak Bang Jali. "Kalau stoknya nol, tulis Habis" itu @if. "Tulis satu baris untuk tiap menu" itu @for. Lampu status pesanan di kasir, yang menyala di salah satu dari diproses, dikirim, atau sampai, itu @switch.

Ketiganya bagian dari template sejak Angular 17, jadi gak perlu import apa pun, dan menggantikan *ngIf, *ngFor, dan [ngSwitch] dari pelajaran sebelumnya. Contoh di sini tetap menulis standalone: true, bentuk yang masih banyak ditemui di kode lama; sejak Angular 19 baris itu bawaan, juga di editor latihan (Angular 22).

🧪 Tebakan cepat: Tiap baris menu punya kotak catatan. Kamu mengetik "tanpa daun bawang" di baris Martabak Manis Cokelat Keju, lalu urutan menunya dibalik. Kalau @for-nya ditulis dengan track $index, catatan itu sekarang ada di baris martabak yang mana? Jawabannya ada di bagian "track: cara Angular mengenali baris".

@if, @else if, @else

import { Component } from '@angular/core'

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <ul>
      @for (m of menu; track m.id) {
        <li>
          {{ m.nama }}
          @if (m.stok === 0) {
            <b>Habis</b>
          } @else if (m.stok < 5) {
            <b>Sisa {{ m.stok }}</b>
          } @else {
            <b>Tersedia</b>
          }
        </li>
      }
    </ul>
  `,
})
export class App {
  menu = [
    { id: 1, nama: 'Martabak Manis Cokelat Keju', stok: 4 },
    { id: 2, nama: 'Martabak Telur Spesial', stok: 6 },
    { id: 3, nama: 'Terang Bulan Pandan', stok: 0 },
  ]
}
Menu stok Cabang yang jalan Tampil
Martabak Manis Cokelat Keju 4 @else if (m.stok < 5) Sisa 4
Martabak Telur Spesial 6 @else Tersedia
Terang Bulan Pandan 0 @if (m.stok === 0) Habis

Latihan pertama memakai bentuk yang sama untuk tombol login:

@if (loggedIn) {
  <p>Selamat datang!</p>
} @else {
  <p>Silakan login</p>
}
<button (click)="loggedIn = !loggedIn">{{ loggedIn ? 'Logout' : 'Login' }}</button>

Mula-mula loggedIn bernilai false, jadi yang tampil Silakan login. Klik pertama membuatnya true dan paragrafnya diganti Selamat datang!; klik kedua mengembalikannya.

@for dan @empty

<ul>
  @for (m of menu; track m.id) {
    <li>{{ $index + 1 }}. {{ m.nama }}</li>
  } @empty {
    <li>Menu habis hari ini</li>
  }
</ul>
Baris $index $first $last $even $count
Martabak Manis Cokelat Keju 0 true false true 3
Martabak Telur Spesial 1 false false false 3
Terang Bulan Pandan 2 false true true 3

track: cara Angular mengenali baris

Saat array berubah, Angular gak membuang semua <li> lalu membuat ulang. Dia mencocokkan baris lama dengan isi baru lewat nilai track, lalu cuma memindah, menambah, atau membuang yang perlu. Jadi track gunanya melacak identitas item.

Misalnya tiap <li> punya <input placeholder="Catatan" />, kamu mengetik "tanpa daun bawang" di baris Martabak Manis Cokelat Keju, lalu balik() menjalankan this.menu = [...this.menu].reverse():

track Urutan sesudah dibalik Catatan "tanpa daun bawang" ada di
m.id Terang Bulan Pandan, Martabak Telur Spesial, Martabak Manis Cokelat Keju baris ketiga, tetap di Martabak Manis Cokelat Keju
$index sama baris pertama, sekarang Terang Bulan Pandan

Dengan track m.id, elemen <li> milik Martabak Manis Cokelat Keju ikut pindah ke bawah bersama kotak catatannya. Dengan track $index, Angular menganggap "baris ke-0 tetap baris ke-0": elemennya diam di tempat, cuma teksnya yang diganti, jadi catatanmu sekarang menempel di Terang Bulan Pandan. Itu jawaban tebakannya.

@switch untuk status pesanan

@switch (status) {
  @case ('diproses') { <p>Martabak sedang dibuat</p> }
  @case ('dikirim') { <p>Kurir sedang di jalan</p> }
  @case ('sampai') { <p>Pesanan sudah sampai</p> }
  @default { <p>Status tidak dikenal</p> }
}

⚠️ Jebakan yang sering ketemu

TL;DR: @if (syarat) { ... } @else if (...) { ... } @else { ... } merender cabang pertama yang benar dan membuang sisanya dari DOM; as menyimpan hasil syaratnya. @for (m of menu; track m.id) { ... } @empty { ... } mengulang satu bagian untuk tiap isi array, dengan $index, $first, $last, $even, dan $count; track wajib dan gunanya melacak identitas item, jadi saat daftar dibalik, track m.id memindah barisnya sedangkan track $index cuma mengganti teksnya. @switch (status) merender @case yang nilainya === status, atau @default. Semuanya bawaan template sejak Angular 17, tanpa import.

Yang akan kamu pelajari