Tổng hợp 67 câu hỏi phỏng vấn Angular kèm đáp án chi tiết, song ngữ Việt–Anh — sắp xếp từ cơ bản đến nâng cao. Ôn luyện miễn phí, tự động lưu tiến độ.
Angular là framework frontend full-featured dùng TypeScript để xây dựng SPA, enterprise app và hybrid-rendered web app. AngularJS là dòng 1.x cũ, khác kiến trúc hoàn toàn và không nên gọi lẫn với Angular hiện đại. So với React/Vue, Angular opinionated hơn: có DI, Router,…
Component là building block chính của Angular UI. Một component thường gồm class TypeScript chứa state/logic, template HTML chứa binding, style CSS scoped theo component và metadata trong @Component như selector, templateUrl, styleUrl, imports. Với standalone component, dependency được khai báo trực tiếp trong imports…
Standalone component là component tự quản lý các dependencies của nó thông qua mảng imports bên trong decorator @Component và có thể bootstrap trực tiếp bằng bootstrapApplication() mà không cần đến NgModule. Lợi ích chính: - Giảm boilerplate: Loại bỏ sự cồng kềnh của NgModule.…
Với standalone app, entrypoint thường gọi bootstrapApplication(AppComponent, appConfig). Ví dụ cấu hình root phổ biến: Cách này thay thế pattern cũ platformBrowserDynamic().bootstrapModule(AppModule) trong nhiều project mới, giúp root configuration nằm trong provider functions tree-shakable và dễ tách theo môi trường.
NgModule vẫn là public API và vẫn gặp nhiều trong enterprise codebase. Vai trò chính còn lại: gom declarations/providers trong legacy modules, expose library API cũ, cấu hình forRoot/forChild, hoặc bridge với third-party package chưa standalone. Với app mới, NgModule không còn là đơn vị…
Các hook hay gặp: ngOnChanges chạy khi input đổi, lần đầu chạy trước ngOnInit; ngOnInit chạy một lần sau khi input initial xong; ngAfterViewInit dùng khi view/query đã sẵn sàng; ngOnDestroy hoặc DestroyRef dùng cleanup. Ví dụ cleanup hiện đại: Từ Angular hiện đại, afterNextRender/afterEveryRender…
Angular compiler phân tích template trước runtime, bind với TypeScript types và phát hiện lỗi như sai input name, sai kiểu truyền vào component, pipe không tồn tại hoặc variable template không hợp lệ. Bật strict template checking trong tsconfig giúp bắt lỗi sớm trong…
Interpolation {{ value }} render text ra template. Property binding [disabled]="isSaving()" set property DOM/component input theo expression. Event binding (click)="save()" lắng nghe event và gọi method. Quy tắc nhanh: dùng {{ }} cho text, [ ] để đẩy dữ liệu xuống view/component con, ( )…
[(ngModel)] là cú pháp banana-in-a-box kết hợp property binding và event binding: dữ liệu đi xuống input, thay đổi từ input đẩy ngược lên model. Nó thuộc FormsModule và phù hợp với form đơn giản. Với form phức tạp, validation nhiều bước hoặc test nghiêm…
input() hoặc @Input() nhận data từ parent xuống child. output() hoặc @Output() phát event từ child lên parent. Pattern chuẩn là one-way data flow: parent sở hữu state, child nhận input và emit event khi user tương tác. Tránh để child mutate object input trực…
input() tạo một InputSignal đọc bằng cách gọi function, ví dụ userId(), và compose tự nhiên với computed() hoặc effect(). Ví dụ: @Input() vẫn dùng được, nhất là trong code cũ; nhưng khi viết component mới, signal input giúp template và reactive state nhất quán…
model() định nghĩa input có thể ghi, đồng thời tạo output <nameChange để hỗ trợ two-way binding cho custom component. Ví dụ checkbox tự emit thay đổi: Dùng cho component chỉnh sửa một giá trị như checkbox/date picker; nếu component chỉ render dữ liệu, dùng…
Directive là class gắn behavior vào DOM hoặc template. Attribute directive thay đổi behavior/appearance của element có sẵn, ví dụ highlight hoặc permission state. Structural directive thay đổi cấu trúc DOM bằng cách thêm/xoá view. Trong Angular hiện đại, legacy ngIf, ngFor, ngSwitch đã bị…
Control flow block là cú pháp template built-in, không cần import directive và dễ type-check hơn. Ví dụ: Từ Angular v20, NgIf, NgFor, NgSwitch đã deprecate, nên code mới nên dùng block syntax.
track cho Angular biết item nào là cùng một entity khi list thay đổi, giúp reuse DOM/component instance thay vì destroy/recreate sai cách. Ví dụ đúng với dữ liệu có id: Với list tĩnh có thể track item; hạn chế dùng index nếu list có…
@defer cho phép trì hoãn load/render một phần template và dependencies của nó theo trigger như viewport, interaction, hover, timer hoặc idle. Ví dụ: Dùng cho UI chưa cần ngay để giảm initial bundle và cải thiện Core Web Vitals.
ng-content cho phép parent truyền markup vào layout của child component, tương tự slot. Ví dụ card có slot tiêu đề và nội dung: Dùng khi xây component wrapper như card, modal, tabs, layout shell, nơi child quyết định khung còn parent quyết định nội…
Signal là reactive value được đọc bằng cách gọi function, ví dụ count(), và được cập nhật bằng set() hoặc update(). Khi signal được đọc trong template hoặc computed, Angular track dependency đó; khi value đổi, phần phụ thuộc được cập nhật. Signal giúp state…
signal giữ state có thể ghi; computed derive giá trị read-only; effect chạy side effect khi dependency signal đổi. Ví dụ: Không nên dùng effect để propagate state giữa signals nếu computed hoặc linkedSignal biểu đạt được quan hệ đó rõ hơn.
View query đọc element/component nằm trong template của chính component; content query đọc nội dung parent project vào qua ng-content. Ví dụ signal query hiện đại: Dùng query khi cần tương tác với child component/directive hoặc DOM API thật. Không dùng query chỉ để truyền…
Observable biểu diễn stream theo thời gian, có cancellation, operators mạnh và phù hợp với HTTP, WebSocket, router events hoặc async pipelines. Bridge khi cần đưa stream vào template signal-based: Signal biểu diễn current value đồng bộ, đọc trực tiếp trong template và phù hợp…
ChangeDetectionStrategy.OnPush giảm số lần check component bằng cách chỉ cập nhật khi input reference đổi, event trong component xảy ra, async pipe emit, signal được đọc trong template đổi, hoặc component được mark for check. Nó hiệu quả khi state immutable và component tree lớn.…
async pipe subscribe Observable/Promise, render latest value và tự unsubscribe khi view bị destroy. Nó giảm memory leak so với subscribe thủ công trong component. Với OnPush, mỗi lần Observable emit, async pipe cũng mark component để update. Nếu cần transform nhiều stream phức tạp,…
Pipe transform dữ liệu trong template. Mặc định pipe là pure: Angular chỉ gọi lại khi primitive value đổi hoặc object/array reference đổi, nên hiệu năng tốt hơn. Ví dụ custom pure pipe: Impure pipe pure: false có thể bắt mutation bên trong object/array nhưng…
Dependency Injection là cơ chế để class nhận dependency từ Angular injector thay vì tự new dependency đó. Component/service chỉ khai báo cần gì, còn provider quyết định instance nào được cấp. Lợi ích: code dễ test, dễ mock, giảm coupling và quản lý singleton/shared…
providedIn: "root" đăng ký service ở root injector, thường là singleton toàn app và tree-shakable nếu không dùng. Ví dụ component provider tạo store riêng cho mỗi wizard: Provider trong component tạo instance ở injector của component đó và áp dụng cho subtree bên dưới.…
Constructor injection khai báo dependency qua constructor parameters, rõ ràng và quen thuộc. Ví dụ functional guard dùng inject(): inject() gọn hơn cho guards, resolvers, interceptors hoặc field initializers; chỉ gọi trong injection context hợp lệ.
InjectionToken dùng khi dependency không phải class concrete, ví dụ config object, primitive value, feature flag, API URL hoặc interface không tồn tại ở runtime. Ví dụ: Với config cần lazy hoặc phụ thuộc dependency khác, provider có thể dùng useFactory.
useClass tạo instance từ class cụ thể, thường để đổi implementation. Ví dụ các provider strategy: useValue cấp object/value có sẵn, useFactory tạo dependency động và có thể inject dependency khác, useExisting alias token này sang token khác để reuse cùng instance.
Angular Router map URL sang component thông qua route config. App standalone thường dùng provideRouter(routes), template đặt <router-outlet / làm nơi render route hiện tại, và navigation dùng routerLink hoặc Router.navigate(). Route có thể chứa path params, query params, redirects, nested routes, lazy loading, guards…
Với standalone component, route có thể dùng loadComponent; với feature có nhiều child routes, dùng loadChildren để import route array. Ví dụ: Nên đặt boundary theo feature/screen thật sự, không tách quá nhỏ khiến waterfall request tăng.
Không. Route guard chỉ kiểm soát navigation phía client để cải thiện UX, ví dụ redirect user chưa login hoặc chặn rời form chưa lưu. Bảo mật thật phải nằm ở backend/API authorization vì user có thể gọi API trực tiếp hoặc sửa code client.…
Resolver fetch hoặc chuẩn bị data trước khi route activate, giúp component nhận data đã sẵn sàng và xử lý loading/error ở routing layer. Ví dụ functional resolver: Dùng resolver khi màn hình không có ý nghĩa nếu thiếu data chính, như detail page cần…
withComponentInputBinding() bind path params, query params, matrix params và route data vào component inputs có cùng tên. Ví dụ: Cách này làm component dễ test hơn và giảm coupling với ActivatedRoute.
Cách hiện đại nên ưu tiên withComponentInputBinding() nếu param map trực tiếp vào input. Khi cần đọc router state phức tạp, dùng ActivatedRoute và paramMap/queryParamMap. Ví dụ bridge route param sang signal: Snapshot chỉ phù hợp khi param không đổi trong lifetime component. Nếu route…
Typed Forms giúp FormControl, FormGroup và valueChanges mang đúng TypeScript type, giảm lỗi truy cập field sai hoặc submit payload sai shape. Ví dụ: Trong app lớn, typed forms làm refactor an toàn hơn vì compiler phát hiện form contract bị lệch.
Validator là function nhận AbstractControl và trả về ValidationErrors null. Ví dụ cross-field validator: Async validator phù hợp check server như username đã tồn tại; cần debounce/cancel để không bắn request quá nhiều.
FormArray dùng khi số lượng control động, ví dụ nhiều số điện thoại, danh sách địa chỉ, line items trong invoice hoặc survey questions. Ví dụ thêm phone control động: Nó giữ collection controls theo index và cho phép push/remove/insert. Nếu mỗi item có nhiều…
HttpClient là service chính thức để gọi HTTP API, trả về Observable và hỗ trợ typed response, interceptors, params, headers, progress events và testing utilities. Trong standalone app thường cấu hình bằng provideHttpClient(). Vì Observable của HTTP request là cold, request chỉ chạy khi được…
Interceptor xử lý cross-cutting concern cho request/response: attach auth token, refresh token, correlation id, logging, retry, error normalization hoặc loading indicator. Ví dụ functional interceptor: Nên giữ interceptor mỏng; business transform để trong API service.
switchMap huỷ request trước và lấy request mới nhất, phù hợp search/autocomplete. Ví dụ search box: mergeMap chạy song song, concatMap xếp hàng giữ thứ tự, exhaustMap bỏ qua trigger mới khi request cũ đang chạy. Chọn operator theo concurrency semantics.
Ưu tiên async pipe trong template vì tự unsubscribe. Khi phải subscribe trong class, dùng takeUntilDestroyed() với DestroyRef: Không cần unsubscribe với HTTP Observable hoàn tất một lần, nhưng vẫn cần cẩn thận với streams dài như router events, form valueChanges, interval, WebSocket hoặc Subject…
Lỗi HTTP nên được xử lý ở đúng tầng: component/store xử lý lỗi nghiệp vụ cần hiển thị cụ thể; API service normalize response; interceptor xử lý cross-cutting concern như auth, retry, correlation id hoặc global error logging. Ví dụ service trả fallback có kiểm…
SSR render HTML trên server để cải thiện first content, SEO và perceived performance. Cấu hình hydration phía client thường nằm ở bootstrap: Hydration tái sử dụng HTML đã render thay vì render lại toàn bộ trên client. Cần đảm bảo server/client render deterministic; code…
Các lỗi phổ biến: render dựa vào Date.now()/random, đọc window hoặc localStorage khi server render, format ngày theo timezone khác nhau, mutate DOM bằng library ngoài Angular trước hydration, hoặc API trả data khác giữa server và client. Guard browser-only code: Cách fix là làm…
Bắt đầu bằng route-level lazy loading, kiểm tra bundle analyzer/source-map-explorer, loại bỏ dependency nặng không cần thiết và dùng @defer cho UI chưa cần ngay. Tiếp theo tối ưu shared module/imports để tránh kéo cả thư viện vào initial chunk. Đừng micro-optimize trước khi đo;…
Angular xây accessible component qua: semantic HTML, ARIA attributes, và @angular/cdk/a11y (stable) — bộ utility a11y dùng phổ biến trong production. Các tool chính của CDK a11y: - FocusTrap (cdkTrapFocus) — giữ focus trong modal/dialog, không cho tab ra ngoài. - LiveAnnouncer — đọc thông…
animate.enter và animate.leave là API animation mới được compiler hỗ trợ trực tiếp, dùng CSS class hoặc callback khi element vào/rời DOM. Docs Angular hiện tại khuyến nghị native CSS với hai API này cho code mới; nhiều API trong @angular/animations legacy đã bị deprecate.…
TestBed tạo testing module/environment để render component, inject services và override providers trong unit test. Nó hữu ích khi test component standalone, service có DI, provider override, pipe/directive hoặc behavior cần gần Angular runtime thật. Với logic thuần TypeScript không phụ thuộc Angular runtime, có…
Angular docs hiện tại mô tả project CLI mới dùng Vitest với jsdom mặc định, trong khi Karma vẫn được hỗ trợ cho migration/legacy. Khi phỏng vấn, nên nói rõ bối cảnh version: codebase cũ có thể vẫn Karma/Jasmine, project mới nên cân nhắc Vitest;…
Dùng provideHttpClient() cùng provideHttpClientTesting() để thay backend thật bằng test backend, rồi dùng HttpTestingController để assert request và flush response. Ví dụ: Thứ tự provider quan trọng: provideHttpClient() phải đứng trước provideHttpClientTesting().
Không phải Angular app nào cũng cần global state library. Local component state nên dùng signals; server stream/cache có thể giữ Observable trong service; feature state vừa phải có thể dùng service/store tự viết. Pattern store nhỏ bằng signal: Cân nhắc NgRx/Signal Store khi state…
constructor là của class TypeScript, chạy khi Angular tạo instance — lúc này @Input() chưa được gán. ngOnInit là lifecycle hook của Angular, chạy sau lần ngOnChanges đầu tiên, tức là input đã sẵn sàng. Quy tắc thực tế: - constructor: chỉ nhận dependency (hoặc…
Vì signal phát tín hiệu thay đổi dựa trên so sánh tham chiếu khi bạn ghi giá trị mới. items().push(x) chỉ đọc signal rồi mutate mảng tại chỗ — signal không hề biết có gì thay đổi, nên không thông báo cho template. - set(value):…
Đây là lỗi chỉ xuất hiện ở dev mode. Sau mỗi vòng change detection, Angular chạy thêm một vòng kiểm tra; nếu giá trị binding ở vòng hai khác vòng một, nghĩa là có gì đó thay đổi state sau khi view đã được kiểm…
Với OnPush, Angular chỉ kiểm tra component khi có một trong các tín hiệu: input thay đổi tham chiếu, event từ template của chính nó, async pipe phát giá trị, hoặc signal đọc trong template thay đổi. Ngoài các trường hợp đó, dù dữ liệu…
takeUntilDestroyed() (từ @angular/core/rxjs-interop) hoàn tất Observable khi context bị huỷ, thay cho mẫu destroy$ = new Subject() + ngOnDestroy thủ công. NG0203 nghĩa là bạn gọi một API cần injection context (inject(), takeUntilDestroyed() không tham số) ở nơi Angular không còn giữ context đó —…