{{ product.name }}
{{ product.price | currency:'USD' }}
@if (product.inStock) { } @else { Out of Stock }# Top 25 Pertanyaan Wawancara Angular: Panduan Lengkap untuk Sukses > 25 pertanyaan wawancara Angular paling sering ditanyakan pada 2026. Jawaban detail, contoh kode, dan kiat untuk meraih posisi developer Angular. - Published: 2026-02-04 - Updated: 2026-04-27 - Author: SharpSkill - Tags: angular interview, frontend interview, angular questions, typescript, technical interview - Reading time: 16 min --- Wawancara teknis Angular mengukur pemahaman terhadap arsitektur framework, penguasaan TypeScript, dan praktik terbaik pengembangan frontend. Panduan ini menyajikan 25 pertanyaan yang paling sering ditanyakan beserta jawaban detail dan contoh kode untuk persiapan yang optimal. > **Tips persiapan** > > Pertanyaan-pertanyaan ini mencakup versi Angular terbaru (16+), termasuk Signals, komponen standalone, dan control flow baru. Menguasai konsep modern ini menunjukkan pemantauan teknologi yang aktif. ## Dasar Angular ### 1. Apa perbedaan antara Angular dan AngularJS? Angular (versi 2+) adalah penulisan ulang lengkap dari AngularJS. Perbedaan utama terletak pada arsitektur, bahasa, dan performa. AngularJS menggunakan JavaScript dan pola MVC dengan sistem two-way binding yang dapat menimbulkan masalah performa. Angular menggunakan TypeScript, arsitektur berbasis komponen, dan sistem change detection yang dioptimalkan. ```typescript // AngularJS (1.x) - Controller-based // angular.module('app').controller('UserController', function($scope) { // $scope.user = { name: 'Alice' }; // }); // Angular (2+) - Component-based // user.component.ts import { Component } from '@angular/core'; @Component({ selector: 'app-user', standalone: true, template: `
{{ user.email }}
{{ product.price | currency:'USD' }}
@if (product.inStock) { } @else { Out of Stock }{{ data }}
` }) export class LifecycleDemoComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy { @Input() data = ''; // 1. Called when an @Input changes (before ngOnInit) ngOnChanges(changes: SimpleChanges) { console.log('ngOnChanges', changes); } // 2. Called once after the first ngOnChanges // Ideal for initializations ngOnInit() { console.log('ngOnInit - Component initialization'); } // 3. Called on every change detection cycle // Use with caution (performance) ngDoCheck() { console.log('ngDoCheck'); } // 4. After content projection (ng-content) ngAfterContentInit() { console.log('ngAfterContentInit'); } // 5. After each projected content check ngAfterContentChecked() { console.log('ngAfterContentChecked'); } // 6. After component view initialization // @ViewChild references are available here ngAfterViewInit() { console.log('ngAfterViewInit - View initialized'); } // 7. After each view check ngAfterViewChecked() { console.log('ngAfterViewChecked'); } // 8. Just before component destruction // Cleanup: unsubscribe, clearInterval, etc. ngOnDestroy() { console.log('ngOnDestroy - Cleanup'); } } ``` Hook yang paling sering dipakai adalah `ngOnInit` untuk inisialisasi, `ngOnChanges` untuk merespons perubahan input, dan `ngOnDestroy` untuk membersihkan resource. ### 4. Apa itu Data Binding di Angular? Data binding menghubungkan data komponen dengan template. Angular menyediakan empat bentuk binding. ```typescript // data-binding.component.ts import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-data-binding', standalone: true, imports: [FormsModule], template: `{{ getFullName() }}
Hello, {{ username }}
` }) export class DataBindingComponent { // Properties for interpolation title = 'My Application'; firstName = 'John'; lastName = 'Doe'; // Properties for property binding imageUrl = '/assets/logo.png'; imageAlt = 'Application logo'; isLoading = false; // Property for two-way binding username = ''; getFullName(): string { return `${this.firstName} ${this.lastName}`; } handleClick(): void { console.log('Button clicked'); } onEnter(event: KeyboardEvent): void { const target = event.target as HTMLInputElement; console.log('Entered value:', target.value); } } ``` Two-way binding `[(ngModel)]` adalah kombinasi dari property binding dan event binding yang memungkinkan sinkronisasi otomatis antara model dan view. ### 5. Apa perbedaan antara Module dan Standalone Component? NgModules mengelompokkan komponen, directive, dan service yang saling terkait. Komponen standalone (Angular 14+) memungkinkan pembuatan komponen mandiri tanpa modul. ```typescript // Traditional approach with NgModule // products.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ProductListComponent } from './product-list.component'; import { ProductCardComponent } from './product-card.component'; import { ProductService } from './product.service'; @NgModule({ // Components belonging to this module declarations: [ ProductListComponent, ProductCardComponent ], // Modules needed imports: [CommonModule], // Components usable outside exports: [ProductListComponent], // Services with module scope providers: [ProductService] }) export class ProductsModule {} // Modern approach with Standalone Components // product-list.component.ts import { Component, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ProductCardComponent } from './product-card.component'; import { ProductService } from './product.service'; @Component({ selector: 'app-product-list', // No NgModule needed standalone: true, // Direct dependency imports imports: [CommonModule, ProductCardComponent], template: ` @for (product of products(); track product.id) {{{ user.email }}
} ` }) export class UserProfileComponent implements OnInit { // Injection via inject() (recommended) private userService = inject(UserService); user$!: ObservableDouble: {{ doubleCount() }}
Message: {{ message() }}
No users found
}{{ data }}
` }) export class DefaultStrategyComponent { data = 'Hello'; } // OnPush strategy: checks only if inputs change // or if an event is triggered within the component @Component({ selector: 'app-onpush-strategy', changeDetection: ChangeDetectionStrategy.OnPush, template: `{{ data().name }}
` }) export class OnPushStrategyComponent { private cdr = inject(ChangeDetectorRef); // Signal: automatically triggers detection data = signal({ name: 'Alice' }); update() { // With signal, update is automatic this.data.set({ name: 'Bob' }); } // For cases where manual detection is needed manualUpdate() { // Mark component for checking this.cdr.markForCheck(); // Or force immediate detection this.cdr.detectChanges(); } } // Practical example: optimized list @Component({ selector: 'app-optimized-list', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ` @for (item of items(); track item.id) {{{ message() }}
` }) export class ChildComponent { message = input.required{{ message$ | async }}
` }) export class ComponentB implements OnDestroy { private messageService = inject(MessageService); private destroy$ = new SubjectYour cart is empty
} @else { @for (item of cartStore.items(); track item.id) {{itemCount, plural, =0 {No items} =1 {One item} other {{{itemCount}} items} }
` }) export class AppComponent { itemCount = 5; } // 2. ngx-translate (runtime language switching) // app.config.ts import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http, './assets/i18n/', '.json'); } // Configuration provideTranslateService({ defaultLanguage: 'en', loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient] } }) // language-switcher.component.ts @Component({ selector: 'app-language-switcher', standalone: true, imports: [TranslateModule], template: `{{ 'HOME.WELCOME' | translate:{ name: userName } }}
` }) export class LanguageSwitcherComponent { private translate = inject(TranslateService); userName = 'Alice'; changeLanguage(event: Event) { const lang = (event.target as HTMLSelectElement).value; this.translate.use(lang); } } // assets/i18n/en.json { "HOME": { "TITLE": "Welcome", "WELCOME": "Hello {{name}}!" } } // assets/i18n/fr.json { "HOME": { "TITLE": "Bienvenue", "WELCOME": "Bonjour {{name}} !" } } ``` Pemilihan antara i18n bawaan dan ngx-translate bergantung pada kebutuhan: kompilasi terpisah untuk performa terbaik atau pergantian dinamis untuk fleksibilitas yang lebih besar. ### 25. Apa saja praktik terbaik untuk menyusun proyek Angular? Struktur yang tertata dengan baik mempermudah pemeliharaan dan skalabilitas proyek. ``` src/ ├── app/ │ ├── core/ # Singleton services, guards, interceptors │ │ ├── guards/ │ │ │ └── auth.guard.ts │ │ ├── interceptors/ │ │ │ └── auth.interceptor.ts │ │ ├── services/ │ │ │ ├── auth.service.ts │ │ │ └── api.service.ts │ │ └── core.provider.ts # Provider configuration │ │ │ ├── shared/ # Reusable components, pipes, directives │ │ ├── components/ │ │ │ ├── button/ │ │ │ └── modal/ │ │ ├── directives/ │ │ ├── pipes/ │ │ └── index.ts # Barrel exports │ │ │ ├── features/ # Feature modules (lazy-loaded) │ │ ├── products/ │ │ │ ├── components/ │ │ │ ├── services/ │ │ │ ├── models/ │ │ │ ├── products.routes.ts │ │ │ └── products.component.ts │ │ ├── cart/ │ │ └── checkout/ │ │ │ ├── layouts/ # Page layouts │ │ ├── main-layout/ │ │ └── auth-layout/ │ │ │ ├── app.component.ts │ ├── app.config.ts │ └── app.routes.ts │ ├── assets/ ├── environments/ └── styles/ ``` ```typescript // Best code practices // 1. Barrel exports to simplify imports // shared/index.ts export * from './components/button/button.component'; export * from './components/modal/modal.component'; export * from './pipes/format-date.pipe'; // 2. Centralized provider configuration // core/core.provider.ts import { provideHttpClient, withInterceptors } from '@angular/common/http'; import { authInterceptor } from './interceptors/auth.interceptor'; export const coreProviders = [ provideHttpClient( withInterceptors([authInterceptor]) ), // Other global providers ]; // 3. Typed models // features/products/models/product.model.ts export interface Product { id: number; name: string; price: number; category: ProductCategory; createdAt: Date; } export type ProductCategory = 'electronics' | 'clothing' | 'books'; export interface CreateProductDto { name: string; price: number; category: ProductCategory; } // 4. Functional interceptor // core/interceptors/auth.interceptor.ts import { HttpInterceptorFn } from '@angular/common/http'; import { inject } from '@angular/core'; export const authInterceptor: HttpInterceptorFn = (req, next) => { const authService = inject(AuthService); const token = authService.getToken(); if (token) { req = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next(req); }; ``` Konvensi ini memungkinkan navigasi kode yang intuitif dan memudahkan kolaborasi tim. ## Kesimpulan 25 pertanyaan ini mencakup konsep-konsep esensial Angular yang muncul dalam wawancara. Poin penting yang harus dikuasai: - ✅ **Dasar**: komponen, data binding, siklus hidup, DI - ✅ **Angular modern**: Signals, komponen standalone, control flow baru - ✅ **Reaktivitas**: RxJS, Observable, state management dengan Signals - ✅ **Form**: Template-driven vs Reactive, validasi kustom - ✅ **Routing**: Guards, lazy loading, pengiriman data - ✅ **Performa**: OnPush, defer, virtual scrolling - ✅ **Pengujian**: unit test, mock, HttpTestingController Mempersiapkan diri untuk wawancara Angular memerlukan latihan rutin. Membangun proyek pribadi membantu memantapkan pengetahuan ini dan menjelaskannya secara alami selama wawancara. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/angular/top-25-angular-interview-questions