This episode dissects Angular components and templates: how to create components with the CLI, interpolation, property binding, event binding, class and style binding, template references, and inter-component communication with @Input and @Output.

In episode 3 you got a running Angular project. Now we go to the heart of Angular: components and templates. Everything you see on screen — buttons, forms, lists, cards — is a component rendering a template.
Episode 4 dissects how to create components, use interpolation and the various forms of data binding, template references, and inter-component communication with @Input and @Output. These are skills you'll use in every line of Angular code you write.
The best way to create a component is through the CLI, because the required files are generated automatically and registered correctly.
ng generate component produk
ng g c produk --skip-testsng g c produk --skip-tests creates a produk folder with .ts, .html, and .scss files and no spec file. Once generated, the component can be used in other templates via its selector.
import { Component } from '@angular/core';
@Component({
selector: 'app-produk',
standalone: true,
template: `<h3>Daftar Produk</h3>`,
styleUrl: './produk.component.scss',
})
export class ProdukComponent {
namaToko = 'Toko Online';
}The @Component decorator defines the selector, template, and styleUrl. The namaToko property is component state you can display in the template. A standalone component doesn't need an NgModule to be used.
Interpolation displays values from the component into the template using double braces:
<p>Selamat datang di {{ namaToko }}</p>{{ namaToko }} will display the value of the namaToko property. Angular also supports simple expressions inside the braces, such as {{ 1 + 2 }} or {{ nama.toUpperCase() }}, but avoid complex logic in templates.
[property]="value" sends values from the component to an element.(event)="handler($event)" captures events from an element.[(ngModel)] combines both for forms.<button [disabled]="sedangMuat">Simpan</button>
<input [value]="nama" (input)="nama = $any($event.target).value" />
<div [class.aktif]="terpilih" [style.color]="warna">Item</div>Notice the binding patterns: [disabled] binds a DOM property, (input) captures an event, [class.aktif] adds a class when terpilih is true, and [style.color] binds a style value directly.
A template reference variable (marked with #) gives you access to a DOM element or component within the same template, without manual queries.
<input #cariInput placeholder="Cari produk" />
<button (click)="cari(cariInput.value)">Cari</button>#cariInput is a reference to the input element. When the button is clicked, the value of cariInput.value is sent to the cari method. To access the element from the component class, use viewChild:
import { Component, ElementRef, viewChild } from '@angular/core';
@Component({
selector: 'app-cari',
standalone: true,
template: `<input #cari />`,
})
export class CariComponent {
readonly cari = viewChild<ElementRef<HTMLInputElement>>('cari');
}viewChild('cari') returns a signal containing the input element once the view is ready. This is the modern approach that replaces the decorator-based @ViewChild.
A parent component sends data to a child component through inputs, and the child notifies the parent through outputs. Since Angular 17.2, input and output are available as signal-based functions.
import { Component, input, output } from '@angular/core';
@Component({
selector: 'app-kartu-produk',
standalone: true,
template: `
<div class="kartu" (click)="pilih.emit()">
<h4>{{ produk().nama }}</h4>
<p>Rp {{ produk().harga }}</p>
</div>
`,
})
export class KartuProdukComponent {
readonly produk = input.required<Produk>();
readonly pilih = output();
}The parent then uses <app-kartu-produk [produk]="p" (pilih)="bukaDetail()" />. Notice input.required for required inputs and output() for the event emitted when the card is clicked.
The combination of input and output is what forms the two-way communication pattern between components: the parent sends data via property binding, and the child reports actions via event binding. This pattern is called component communication and is the foundation of Angular's component architecture.
Key takeaways:
input and output replace the classic @Input and @Output.In the next episode, episode 5, we'll cover directives and pipes — using built-in directives such as *ngIf and *ngFor plus the modern @if and @for control flow, creating custom directives, and using and creating pipes to format display data.