Episode ini membahas directives dan pipes: built-in directives seperti *ngIf, *ngFor, ngClass, dan ngStyle beserta kontrol flow modern @if dan @for, cara membuat custom directive dan custom pipe, serta penggunaan pipe bawaan untuk memformat data tampilan.

Komponen memberi struktur, tetapi sebagian besar "kehidupan" template berasal dari directives dan pipes. Directives mengubah tampilan atau perilaku elemen, sedangkan pipes memformat data sebelum ditampilkan.
Episode 5 membahas built-in directives seperti *ngIf, *ngFor, ngClass, dan ngStyle, kontrol flow modern @if dan @for, pembuatan custom directive dan custom pipe, serta pipe bawaan yang sering dipakai. Setelah ini, template kalian akan jauh lebih ekspresif.
Secara klasik, conditional dan loop memakai structural directives dengan tanda bintang:
<li *ngFor="let produk of daftarProduk; trackBy: trackById">
{{ produk.nama }}
</li>
<div *ngIf="sedangMuat; else kosong">Memuat data...</div>
<ng-template #kosong>Belum ada data</ng-template>*ngFor mengulang daftar, sementara *ngIf menampilkan elemen hanya saat kondisinya benar. trackBy membantu Angular mengenali item yang sama sehingga render ulang lebih efisien.
Sejak Angular 17, ada sintaks kontrol flow baru yang lebih ringkas, performa lebih baik, dan tidak memerlukan import:
@for (produk of daftarProduk; track produk.id) {
<p>{{ produk.nama }} - Rp {{ produk.harga }}</p>
} @empty {
<p>Keranjang masih kosong</p>
}
@if (sedangMuat) {
<p>Memuat data...</p>
} @else {
<button (click)="muatData()">Muat Data</button>
}@for ... track produk.id menggantikan *ngFor dengan trackBy, dan blok @empty menangani kondisi daftar kosong tanpa <ng-template> tambahan. Ini adalah cara yang disarankan untuk semua project baru.
*ngIf dan *ngFor. Ditandai tanda bintang.ngClass dan ngStyle.<div [ngClass]="{ aktif: terpilih, error: gagal }">Status</div>
<div [ngStyle]="{ backgroundColor: terpilih ? 'green' : 'gray' }">Warna</div>[ngClass] menerima objek class dengan kondisi, sementara [ngStyle] mengikat nilai style secara langsung. Keduanya tetap berguna meski kontrol flow modern sudah tersedia.
Directive sendiri dibuat dengan @Directive. Contoh directive attribute yang menambah highlight saat elemen di-hover:
import { Directive, ElementRef, HostListener, input } from '@angular/core';
@Directive({
selector: '[appHighlight]',
standalone: true,
})
export class HighlightDirective {
readonly appHighlight = input<string>('yellow');
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter(): void {
this.el.nativeElement.style.backgroundColor = this.appHighlight();
}
@HostListener('mouseleave') onMouseLeave(): void {
this.el.nativeElement.style.backgroundColor = '';
}
}Selector [appHighlight] berarti directive dipakai sebagai attribute: <p appHighlight="lightblue">teks</p>. @HostListener mendengarkan event dari elemen host. Directive standalone bisa langsung dipakai tanpa NgModule.
Pipe memformat data di template dengan operator |. Pipe bawaan yang paling sering dipakai:
<p>{{ harga | currency: 'IDR' }}</p>
<p>{{ dibuatPada | date: 'medium' }}</p>
<p>{{ nama | uppercase }}</p>
<p>{{ persen | percent }}</p>currency, date, uppercase, dan percent adalah pipe bawaan. Pipe async juga sangat penting — dia men-subscribe Observable atau signal otomatis dan membersihkan subscription saat komponen hancur.
Untuk format khusus, buat pipe sendiri dengan @Pipe:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'rupiah',
standalone: true,
})
export class RupiahPipe implements PipeTransform {
transform(nilai: number): string {
return nilai.toLocaleString('id-ID', {
style: 'currency',
currency: 'IDR',
maximumFractionDigits: 0,
});
}
}Pipe di atas dipakai dengan {{ harga | rupiah }}. Class pipe wajib mengimplementasikan PipeTransform dengan method transform. Pipe murni (default) hanya dijalankan ulang saat input-nya berubah, sehingga efisien.
Inti yang harus dibawa pulang:
*ngIf dan *ngFor adalah structural directives klasik; @if dan @for adalah pengganti modernnya.ngClass dan ngStyle mengubah class dan style berdasarkan kondisi.@Directive dan @HostListener.PipeTransform dan dipakai dengan operator |.Di episode 6 selanjutnya kita akan membahas services dan dependency injection — membuat service dan meng-inject-nya ke komponen, provider scope di level root, module, dan component, singleton service dengan hierarchical injectors, serta interceptor dan provider configuration.