Pipe mengubah cara sebuah nilai ditampilkan di template, tanpa mengubah nilainya di class. Ditulis dengan garis tegak: {{ harga | currency:'IDR' }}. Bayangin mesin cetak struk di kasir Martabak Bang Jali. Di laci kasir, harganya tetap angka 50000. Mesin struk yang mencetaknya jadi tulisan rapi dengan simbol mata uang dan titik ribuan. Angka di laci gak berubah; cuma cetakannya yang dirapikan.
🧪 Tebakan cepat:
{{ 50000 | currency:'IDR' }}. Yang tampilRp50.000, atau yang lain? Jawabannya ada di bagian "currency, locale, dan Rupiah".
Pipe: mengubah tampilan, bukan data
import { Component } from '@angular/core'
import { CurrencyPipe, DatePipe, UpperCasePipe } from '@angular/common'
@Component({
selector: 'app-root',
standalone: true,
imports: [UpperCasePipe, DatePipe, CurrencyPipe],
template: `
<h3>{{ nama | uppercase }}</h3>
<p>{{ harga | currency:'IDR' }}</p>
<p>{{ waktu | date:'dd/MM/yyyy HH:mm' }}</p>
`,
})
export class App {
nama = 'Martabak Telur Spesial'
harga = 50000
waktu = new Date(2026, 9, 10, 19, 30)
}
| Di template | Tampil di halaman | Nilai di class |
|---|---|---|
{{ nama | uppercase }} |
MARTABAK TELUR SPESIAL | 'Martabak Telur Spesial' |
{{ harga | currency:'IDR' }} |
IDR50,000.00 | 50000 |
{{ waktu | date:'dd/MM/yyyy HH:mm' }} |
10/10/2026 19:30 | objek Date |
- Simbol
|mengirim nilai di kirinya ke pipe di kanannya. Argumen ditulis sesudah titik dua:date:'dd/MM/yyyy'. Spasi di sekitarnya boleh,date : 'dd/MM/yyyy'juga jalan. - Nilai di class gak tersentuh:
namatetap'Martabak Telur Spesial', jadi bagian lain yang membacanya tetap dapat teks aslinya. - Tiap pipe bawaan punya class di
@angular/common(UpperCasePipe,DatePipe,CurrencyPipe) yang masukimports, tapi di template dipanggil dengan namanya yang pendek:uppercase,date,currency.CommonModulemengimpor semuanya sekaligus. new Date(2026, 9, 10)itu 10 Oktober, karena bulan di JavaScript dihitung dari 0.
Pipe bawaan yang sering dipakai
| Template | Hasil di Angular 18 |
|---|---|
{{ nama | lowercase }} |
martabak telur spesial |
{{ 'martabak telur spesial' | titlecase }} |
Martabak Telur Spesial |
{{ waktu | date }} |
Oct 10, 2026 |
{{ waktu | date:'dd/MM/yyyy' }} |
10/10/2026 |
{{ waktu | date:'HH:mm' }} |
19:30 |
{{ 0.15 | percent }} |
15% |
{{ 50000 | number }} |
50,000 |
{{ menu | json }} |
{ "nama": "Terang Bulan Pandan", "stok": 0 } |
{{ status | async }} |
isi Promise atau Observable begitu datang, misalnya Dikirim |
json berguna untuk mengintip isi objek saat debugging. async menunggu data yang datang belakangan dan menampilkannya begitu sampai; dipakai lagi di pelajaran RxJS dan HttpClient.
currency, locale, dan Rupiah
Tanpa pengaturan apa pun, Angular memformat angka dengan aturan locale en-US: koma untuk ribuan, titik untuk desimal, dua angka di belakang koma. Jadi {{ 50000 | currency:'IDR' }} menampilkan IDR50,000.00, bukan Rp50.000. Itu jawaban tebakannya.
Argumen currency urutannya kode mata uang, cara menampilkan simbol, jumlah digit, lalu locale:
| Template | Hasil |
|---|---|
{{ harga | currency:'IDR' }} |
IDR50,000.00 |
{{ harga | currency:'IDR':'symbol-narrow' }} |
Rp50,000.00 |
{{ harga | currency:'IDR':'symbol-narrow':'1.0-0' }} |
Rp50,000 |
{{ harga | currency:'IDR':'symbol':'1.0-0':'id' }} |
Rp50.000 |
{{ 1234500 | currency:'IDR':'symbol':'1.0-0':'id' }} |
Rp1.234.500 |
'1.0-0'artinya minimal 1 digit sebelum koma, dan 0 sampai 0 digit sesudahnya, jadi tanpa desimal.'id'meminta aturan Indonesia: titik untuk ribuan, dan simbolnya Rp. Data aturan itu gak ikut terpasang; daftarkan sekali di awal aplikasi:
import { registerLocaleData } from '@angular/common'
import localeId from '@angular/common/locales/id'
registerLocaleData(localeId)
- Lupa mendaftarkannya, dan teksnya kosong. Console menulis
ERROR NG0701: Missing locale data for the locale "id". - Dengan data itu,
dateikut berbahasa Indonesia:{{ waktu | date:'EEEE, d MMMM y':'':'id' }}menampilkan Sabtu, 10 Oktober 2026. - Supaya gak menulis
'id'di tiap pipe, proyek bisa memasang{ provide: LOCALE_ID, useValue: 'id' }diproviders. Sesudah itu{{ harga | currency:'IDR' }}langsung jadi Rp50.000,00.
Merangkai pipe dan pipe buatan sendiri
Pipe bisa dirangkai; hasil yang kiri jadi masukan yang kanan:
<p>{{ nama | uppercase | slice:0:8 }}</p>
<!-- MARTABAK -->
Untuk format yang dipakai di banyak tempat, buat pipe sendiri:
import { Pipe, PipeTransform } from '@angular/core'
@Pipe({ name: 'rupiah', standalone: true })
export class RupiahPipe implements PipeTransform {
transform(nilai: number): string {
return 'Rp' + nilai.toLocaleString('id-ID')
}
}
name: 'rupiah'adalah nama yang ditulis di template:{{ harga | rupiah }}menampilkan Rp50.000, dan{{ 1234500 | rupiah }}menampilkan Rp1.234.500.transformmenerima nilai di kiri|dan mengembalikan teks yang tampil. Argumen pipe, kalau ada, jadi parameter berikutnya.toLocaleString('id-ID')memakai format bawaan browser, jadi gak butuhregisterLocaleData.- Masukkan
RupiahPipekeimportskomponen yang memakainya. Di Angular 18, tanpastandalone: truepipe-nya ditolak:The "RupiahPipe" pipe, imported from "App", is not standalone. Did you forget to add the standalone: true flag?Sejak Angular 19, termasuk di editor latihan (Angular 22), pipe sudah standalone tanpa baris itu.
🤔 Pipe itu pure: kapan dia jalan ulang
Pipe bawaan dan pipe buatanmu defaultnya pure: Angular menjalankannya ulang cuma kalau nilai masukannya diganti. Untuk array, "diganti" artinya array baru, bukan isi array lama yang ditambah.
@Pipe({ name: 'totalHarga', standalone: true })
export class TotalHargaPipe implements PipeTransform {
transform(keranjang: number[]): number {
return keranjang.reduce((total, harga) => total + harga, 0)
}
}
// template: <p>Total: {{ keranjang | totalHarga | rupiah }}</p>
| Aksi | keranjang |
Total yang tampil |
|---|---|---|
| Awal | [50000] |
Rp50.000 |
this.keranjang.push(35000) |
[50000, 35000] |
Rp50.000, pipe gak jalan ulang |
this.keranjang = [...this.keranjang, 35000] |
[50000, 35000, 35000] |
Rp120.000 |
Jadi kalau datanya array atau objek, ganti dengan yang baru. @Pipe({ ..., pure: false }) membuat pipe jalan di tiap pengecekan template; benar hasilnya, tapi boros.
⚠️ Jebakan yang sering ketemu
- Lupa memasukkan pipe ke
imports. Seluruh komponen gagal tampil:NG0302: The pipe 'uppercase' could not be found in the 'App' component. Verify that it is included in the '@Component.imports' of this component. - Menulis nama class di template.
{{ nama | UpperCasePipe }}juga NG0302. Class untukimports, nama pendek untuk template. - IDR tanpa locale
id. Hasilnya IDR50,000.00. Untuk Rp50.000, pakai'symbol':'1.0-0':'id'plusregisterLocaleData, atau piperupiahsendiri. - Array yang di-
push. Pipe pure gak melihatnya. Buat array baru. - Teks yang diketik sudah jadi. Latihan mengecek
| uppercasedi template dan<p>berisi persisBELAJAR ANGULAR. MengetikBELAJAR ANGULARlangsung atau memakai.toUpperCase()gak lolos.
TL;DR: Pipe mengubah tampilan sebuah nilai di template tanpa mengubah datanya: {{ nilai | namaPipe:argumen }}, dan class pipe-nya (misalnya UpperCasePipe dari @angular/common) masuk imports. Yang sering dipakai: uppercase, lowercase, titlecase, date:'dd/MM/yyyy', percent, number, json, async, dan currency. currency:'IDR' memakai aturan en-US dan menampilkan IDR50,000.00; untuk Rp50.000 tulis currency:'IDR':'symbol':'1.0-0':'id' dan daftarkan locale-nya dengan registerLocaleData(localeId), kalau gak, console menulis NG0701. Pipe bisa dirangkai dari kiri ke kanan, dan pipe sendiri dibuat dengan @Pipe({ name: 'rupiah', standalone: true }) plus method transform. Pipe itu pure: dia jalan ulang cuma kalau masukannya diganti, jadi array yang di-push gak memicunya.