Component Angular, dilihat dari React
NgModule (dan sekilas standalone component), data binding, structural directive v16, dan Lifecycle Hook
1. Component = class + template + selector
Di React, component adalah function yang mengembalikan JSX. Di Angular, component terdiri dari
"An HTML template that declares what renders on the page", "A TypeScript class that defines behavior",
dan "A CSS selector that defines how the component is used in a template"
[1].
Template dan logika dipisah, lalu disambungkan oleh decorator @Component.
// product-card.component.ts
@Component({
selector: 'app-product-card', // dipakai sebagai <app-product-card>
templateUrl: './product-card.component.html',
styleUrls: ['./product-card.component.css'],
})
export class ProductCardComponent {
@Input() product!: Product; // parent → child (seperti props)
@Output() deleted = new EventEmitter<number>(); // child → parent (seperti callback prop)
}
2. NgModule: wadah yang tidak ada di React
"An NgModule is a class marked by the @NgModule decorator", dan NgModule
"configure the injector and the compiler and help organize related things together"
[2].
Di React, Anda cukup import component lalu memakainya. Di Angular berbasis NgModule, template
hanya mengenal component, directive, dan pipe yang terdaftar di module-nya.
| Array | Isinya | Padanan Node/React |
|---|---|---|
declarations | Component, directive, pipe milik module ini | Daftar file component di folder fitur |
imports | Module lain yang dibutuhkan template (mis. FormsModule) | import paket npm |
providers | Service untuk DI (dibahas di 0014) | Context Provider; providers di NestJS |
bootstrap | Root component, biasanya AppComponent | createRoot(...).render(<App />) |
@NgModule({
declarations: [AppComponent, ProductCardComponent],
imports: [BrowserModule, FormsModule, HttpClientModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Peran keempat array ini dirangkum di dokumentasi v16: declarations "Declares which components, directives, and pipes belong to the module",
imports mengambil "other modules with the components, directives, and pipes that components in the current module need",
dan "@NgModule can also add service providers to the application dependency injectors"
[2].
Sekilas standalone component. Di v16, component juga bisa ditandai standalone: true:
"Standalone components specify their dependencies directly instead of getting them through NgModules",
dan aplikasi bisa di-bootstrap tanpa NgModule lewat bootstrapApplication
[3].
Ini lebih mirip function component React. Tapi ng new di v16 baru menghasilkan aplikasi standalone kalau diberi flag --standalone
[4],
jadi codebase v16 di perusahaan kemungkinan besar masih memakai AppModule. Kuasai NgModule dulu.
@Component({
selector: 'app-product-card',
standalone: true,
imports: [CommonModule], // dependensi disebut di component itu sendiri
templateUrl: './product-card.component.html',
})
export class ProductCardComponent {}
3. Data binding: empat bentuk, dua arah
Setiap binding punya "a target which will receive the bound value" dan "a template expression which produces a value from the model" [5]. Kuncinya ada di bentuk kurungnya:
| Sintaks | Nama | Arah data | Padanan JSX |
|---|---|---|---|
{{ product.name }} | Interpolation | class → tampilan | {product.name} |
[disabled]="isSaving" | Property binding | class → elemen | disabled={isSaving} |
(click)="save()" | Event binding | elemen → class | onClick={save} |
[(ngModel)]="name" | Two-way binding | dua arah | value={name} onChange={e => setName(...)} |
Property binding "moves a value in one direction, from a component's property into a target element property"
[6].
Event binding "lets you listen for and respond to user actions such as keystrokes, mouse movements, clicks, and touches"
[7].
Two-way binding "is a combination of square brackets and parentheses, [()]" (sering disebut banana in a box),
dan untuk elemen form ia "requires NgModel"
[8],
yang datang dari FormsModule
[9].
Antar component: "@Input() lets a parent component update data in the child component.
Conversely, @Output() lets the child send data to a parent component"
[10].
Ini sama dengan props dan callback prop di React. Bedanya, child Angular memanggil this.deleted.emit(id), lalu parent mendengarnya dengan
(deleted)="onDelete($event)".
4. Structural directive (sintaks v16)
"Structural directives are directives which change the DOM layout by adding and removing DOM elements"
[11].
Tanda bintang adalah singkatan: "Angular transforms the asterisk in front of a structural directive into an <ng-template>".
<p *ngIf="products.length === 0; else list">Belum ada Product.</p> <!-- {cond && ...} / ternary -->
<ng-template #list>
<ul>
<li *ngFor="let p of products; trackBy: trackById">{{ p.name }}</li> <!-- products.map(p => <li key={p.id}>) -->
</ul>
</ng-template>
<ng-container *ngIf="isAdmin"> <!-- seperti <>...</> Fragment: tanpa elemen tambahan -->
<app-product-card *ngFor="let p of products" [product]="p" (deleted)="onDelete($event)"></app-product-card>
</ng-container>
<div [ngSwitch]="product.status">
<span *ngSwitchCase="'active'">Aktif</span>
<span *ngSwitchDefault>Nonaktif</span>
</div>
- Satu per elemen. "You may apply only one structural directive to an element" [11]. Butuh
*ngIfdan*ngForsekaligus? Bungkus dengan<ng-container>, yaitu "a grouping element that doesn't interfere with styles or layout" [9]. trackByadalah padanankeydi React: Angular hanya merender ulang item yang berubah [9].- Jangan pakai
@if/@fordi jawaban. Itu control flow Angular 17. Kalau Anda menyebutnya, sebutkan juga bahwa itu sintaks versi yang lebih baru.
5. Lifecycle Hook vs useEffect
| Angular | Kapan dipanggil | Padanan React |
|---|---|---|
constructor | Saat class dibuat. Hanya untuk inject dependency. | Badan function sebelum hook |
ngOnChanges(changes) | "Called before ngOnInit() (if the component has bound inputs) and whenever one or more data-bound input properties change" | useEffect(..., [productId]) |
ngOnInit() | "Called once, after the first ngOnChanges()" | useEffect(..., []) (mount) |
ngOnDestroy() | "Called immediately before Angular destroys the directive or component" | fungsi cleanup yang di-return useEffect |
Kutipan di tabel berasal dari dokumentasi Lifecycle Hook v16 [12].
Dua aturan yang sering ditanyakan berasal dari halaman yang sama:
"You should not, for example, fetch data in a component constructor" dan
"An ngOnInit() is a good place for a component to fetch its initial data".
Di ngOnDestroy, "Unsubscribe Observables and detach event handlers to avoid memory leaks"
[12]
(detail unsubscribe dibahas di 0015).
export class ProductDetailComponent implements OnChanges, OnInit, OnDestroy {
@Input() productId!: number;
private sub?: Subscription;
constructor(private products: ProductService) {} // inject saja, jangan fetch
ngOnChanges(changes: SimpleChanges) { // input berubah
if (changes['productId'] && !changes['productId'].firstChange) this.load();
}
ngOnInit() { this.load(); } // data awal
ngOnDestroy() { this.sub?.unsubscribe(); } // cleanup
private load() {
this.sub?.unsubscribe();
this.sub = this.products.getById(this.productId).subscribe(p => (this.product = p));
}
product?: Product;
}
Latihan 1 — Kuis campuran
Topiknya sengaja diselang-seling. Jawab tanpa scroll ke atas; kalau ragu, tebak dulu, lalu baca penjelasannya.
Kuis di lesson ini adalah feedback cepat, bukan bukti penguasaan; yang dicatat hanya hasil di mock interview 0018.
Latihan 2 — Ucapkan dengan suara keras
Pasang timer 60 detik. Jawab dengan suara keras, seolah sedang interview. Jangan buka jawaban contoh sebelum selesai.
"Anda dari React. Jelaskan bagaimana component Angular 16 disusun dan hidup: NgModule, binding, dan Lifecycle Hook."
Bandingkan dengan jawaban contoh dan checklist-nya
"Di Angular 16 component adalah class TypeScript dengan decorator @Component yang berisi selector, template, dan style.
Component itu dideklarasikan di sebuah NgModule: declarations untuk component milik module,
imports untuk module lain seperti FormsModule, providers untuk service.
Di v16 juga ada standalone component yang mengisi imports sendiri, lebih mirip function component React.
Template terhubung ke class lewat binding: {{ }} interpolation, [prop] property binding,
(event) event binding, dan [(ngModel)] two-way.
Parent ke child lewat @Input() seperti props, child ke parent lewat @Output() dan EventEmitter seperti callback prop.
Untuk kondisi dan list saya pakai *ngIf dan *ngFor dengan trackBy.
Lifecycle-nya: constructor hanya untuk inject dependency, ngOnInit untuk ambil data awal,
ngOnChanges saat input berubah, dan ngOnDestroy untuk unsubscribe,
mirip mount, dependency, dan cleanup di useEffect."
Checklist: apakah Anda menyebut…
- isi
@Component(selector, template, style) dan perannya sebagai class? declarations/imports/providersdi NgModule?- standalone component sebagai alternatif, dan padanannya di React?
- empat bentuk binding dan arah datanya?
@Input/@Outputserta*ngIf/*ngFor(sintaks v16)?- constructor vs
ngOnInit/ngOnChanges/ngOnDestroydengan padananuseEffect?
Kalau kurang dari 4 poin, ulangi sebelum lesson 0014. Soal ini juga akan muncul lagi di mock interview 0018.
Ringkasan untuk dicetak: Reference: Angular 16 dasar untuk developer React · Istilah: GLOSSARY.md
Ada yang belum jelas? Tanyakan ke saya (agent) di terminal, misalnya: "kapan saya butuh ngOnChanges kalau sudah ada ngOnInit?" atau "apa bedanya attribute dan DOM property di property binding?"