{{ product.name }}
{{ product.price | currency:'USD' }}
@if (product.inStock) { } @else { Out of Stock }# 25 คำถามสัมภาษณ์ Angular ยอดนิยม: คู่มือฉบับสมบูรณ์สู่ความสำเร็จ > 25 คำถามสัมภาษณ์ Angular ที่ถูกถามมากที่สุดในปี 2026 พร้อมคำตอบโดยละเอียด ตัวอย่างโค้ด และเคล็ดลับเพื่อคว้าตำแหน่งนักพัฒนา 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 --- การสัมภาษณ์ทางเทคนิคของ Angular จะประเมินความเข้าใจสถาปัตยกรรมของเฟรมเวิร์ก ความเชี่ยวชาญใน TypeScript และแนวปฏิบัติที่ดีในการพัฒนา frontend คู่มือนี้นำเสนอ 25 คำถามที่ถูกถามมากที่สุดพร้อมคำตอบโดยละเอียดและตัวอย่างโค้ดเพื่อการเตรียมตัวที่ดีที่สุด > **เคล็ดลับการเตรียมตัว** > > คำถามเหล่านี้ครอบคลุม Angular เวอร์ชันใหม่ (16+) รวมถึง Signals คอมโพเนนต์ standalone และ control flow รูปแบบใหม่ การเข้าใจแนวคิดสมัยใหม่เหล่านี้แสดงให้เห็นถึงการติดตามเทคโนโลยีอย่างต่อเนื่อง ## พื้นฐานของ Angular ### 1. Angular กับ AngularJS แตกต่างกันอย่างไร? Angular (เวอร์ชัน 2 ขึ้นไป) คือการเขียนใหม่ทั้งหมดของ AngularJS ความแตกต่างหลักอยู่ที่สถาปัตยกรรม ภาษา และประสิทธิภาพ AngularJS ใช้ JavaScript และรูปแบบ MVC ร่วมกับระบบ two-way binding ซึ่งอาจทำให้เกิดปัญหาด้านประสิทธิภาพ Angular ใช้ TypeScript สถาปัตยกรรมที่ยึดตามคอมโพเนนต์ และระบบ change detection ที่ได้รับการปรับแต่งแล้ว ```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 ที่ใช้บ่อยที่สุดคือ `ngOnInit` สำหรับการเริ่มต้น `ngOnChanges` เพื่อตอบสนองต่อการเปลี่ยนแปลง input และ `ngOnDestroy` สำหรับการคืนทรัพยากร ### 4. Data Binding ใน Angular คืออะไร? Data binding เชื่อมข้อมูลของคอมโพเนนต์กับเทมเพลต Angular มี data binding ทั้งหมด 4 รูปแบบ ```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)]` คือการรวม property binding และ event binding เข้าด้วยกัน ทำให้โมเดลและ view ซิงโครไนซ์กันโดยอัตโนมัติ ### 5. Module และ Standalone Component แตกต่างกันอย่างไร? NgModules จัดกลุ่มคอมโพเนนต์ directive และ service ที่เกี่ยวข้องกัน ส่วนคอมโพเนนต์ standalone (Angular 14+) ช่วยให้สร้างคอมโพเนนต์ที่เป็นอิสระได้โดยไม่ต้องใช้โมดูล ```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}} !" } } ``` การเลือกระหว่าง i18n ในตัวกับ ngx-translate ขึ้นอยู่กับความต้องการ: การคอมไพล์แยกเพื่อประสิทธิภาพสูงสุด หรือการสลับแบบไดนามิกเพื่อความยืดหยุ่นมากขึ้น ### 25. แนวปฏิบัติที่ดีที่สุดในการจัดโครงสร้างโปรเจกต์ Angular คืออะไร? โครงสร้างที่จัดวางอย่างเป็นระเบียบช่วยให้การบำรุงรักษาและการขยายโปรเจกต์ง่ายขึ้น ``` 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); }; ``` ข้อตกลงเหล่านี้ช่วยให้นำทางในโค้ดได้อย่างเป็นธรรมชาติและทำงานเป็นทีมได้ง่ายขึ้น ## บทสรุป คำถาม 25 ข้อนี้ครอบคลุมแนวคิด Angular ที่สำคัญซึ่งมักถูกถามในการสัมภาษณ์ ประเด็นสำคัญที่ควรเชี่ยวชาญ: - ✅ **พื้นฐาน**: คอมโพเนนต์, data binding, วงจรชีวิต, DI - ✅ **Angular สมัยใหม่**: Signals, คอมโพเนนต์ standalone, control flow ใหม่ - ✅ **ความเป็น reactive**: RxJS, Observable, การจัดการสถานะด้วย Signals - ✅ **ฟอร์ม**: Template-driven vs Reactive, การตรวจสอบแบบกำหนดเอง - ✅ **Routing**: Guards, lazy loading, การส่งข้อมูล - ✅ **ประสิทธิภาพ**: OnPush, defer, virtual scrolling - ✅ **การทดสอบ**: unit test, mock, HttpTestingController การเตรียมตัวสำหรับการสัมภาษณ์ Angular ต้องอาศัยการฝึกฝนอย่างสม่ำเสมอ การสร้างโปรเจกต์ส่วนตัวช่วยตอกย้ำความรู้เหล่านี้และอธิบายได้อย่างเป็นธรรมชาติในระหว่างสัมภาษณ์ --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/th/blog/angular/top-25-angular-interview-questions