- Angular là gì? Khác AngularJS, React và Vue như thế nào?
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 trong Angular gồm những phần nào?
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à gì và tại sao Angular khuyến nghị dùng?
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.…
- Angular application bootstrap hiện đại hoạt động như thế nào?
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 còn vai trò gì trong Angular hiện đại?
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ị…
- Lifecycle hooks trong Angular chạy theo thứ tự nào và dùng khi nào?
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 và template type checking giúp gì cho production app?
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, property binding và event binding khác nhau thế nào?
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, ( )…
- Two-way binding `[(ngModel)]` hoạt động thế nào?
[(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 và Output trong Angular component dùng để làm gì?
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…
- Signal input `input()` khác `@Input()` truyền thống thế nào?
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 input `model()` dùng khi nào?
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 trong Angular là gì? Structural directive khác attribute directive thế nào?
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 mới `@if`, `@for`, `@switch` khác `*ngIf`, `*ngFor` thế nào?
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.
- Tại sao `track` trong `@for` quan trọng?
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` block dùng để làm gì?
@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.
- Content projection với `ng-content` dùng khi nào?
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 trong Angular là gì?
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`, `computed` và `effect` khác nhau thế nào?
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 và content query khác nhau thế nào?
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…
- Trong Angular, làm sao đưa async data (HTTP) vào signal-based code? `toSignal()` khác `resource()` thế nào?
- Observable và Signal khác nhau thế nào trong Angular?
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…
- OnPush change detection hoạt động thế nào?
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.…
- Zoneless Angular là gì và khi nào nên cân nhắc?
- `async` pipe giúp gì khi dùng Observable trong template?
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,…
- Pure pipe và impure pipe khác nhau thế nào?
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 trong Angular là gì?
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"` khác provider trong component thế nào?
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.…
- `inject()` khác constructor injection thế nào?
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 nào?
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.
- Hierarchical injectors ảnh hưởng thế nào đến state và memory leak?
- Provider strategies `useClass`, `useValue`, `useFactory`, `useExisting` khác nhau thế nào?
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 cơ bản gồm những gì?
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…
- Lazy loading route trong Angular hiện đại làm thế nào?
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.
- Route guards có bảo mật API thật sự khô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 trong Angular Router dùng khi nào?
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()` giúp gì khi đọc route params?
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 route params và query params trong Angular như thế nào?
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 Reactive Forms giải quyết vấn đề gì?
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.
- Custom validator trong Reactive Forms viết như thế nào?
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.
- ControlValueAccessor dùng khi nào?
- FormArray dùng khi nào?
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…
- Reactive Forms vs Template-driven Forms trong Angular khác nhau thế nào? Khi nào dùng cái nào?
- HttpClient trong Angular dùng để làm gì?
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…
- HTTP interceptor dùng khi nào?
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`, `mergeMap`, `concatMap`, `exhaustMap` khác nhau thế nào trong Angular?
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.
- Làm sao tránh memory leak khi subscribe Observable?
Ư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…
- Xử lý lỗi HTTP trong Angular nên làm ở đâu?
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…
- Angular SSR và hydration giải quyết vấn đề gì?
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…
- Hydration trong Angular SSR là gì? Non-destructive hydration hoạt động thế nào?
- Các lỗi hydration mismatch phổ biến trong Angular là gì?
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…
- Tối ưu bundle Angular nên bắt đầu từ đâu?
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 hỗ trợ accessibility (a11y) thế nào? CDK a11y module cung cấp gì?
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` khác legacy Angular animations thế nào?
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.…
- Angular TestBed dùng để làm gì?
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 CLI testing hiện đại dùng Karma hay Vitest?
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;…
- Test HttpClient trong Angular như thế nào?
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().
- Khi nào Angular app cần NgRx, Signal Store hoặc state management library?
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…
- Khi migrate Angular legacy app lên phiên bản mới, quy trình an toàn là gì?
- Nên đặt code khởi tạo ở `constructor` hay `ngOnInit`? Vì sao?
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…
- Signal chứa array/object: vì sao `items().push(x)` không làm UI cập nhật? `set` và `update` khác nhau thế nào?
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):…
- Lỗi `ExpressionChangedAfterItHasBeenCheckedError` (NG0100) do đâu và sửa thế nào?
Đâ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…
- Component đặt `OnPush` nhưng dữ liệu đổi mà UI không cập nhật — chẩn đoán và xử lý thế nào?
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` dùng thế nào cho đúng? Vì sao đôi khi báo lỗi NG0203?
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 đó —…
- Chuyển một app Angular sang zoneless: những chỗ nào hỏng và phải sửa gì?
- Khi nào **không** nên dùng `effect()`? Dùng gì thay thế?
- Thiết kế luồng refresh token bằng HTTP interceptor: xử lý sao để nhiều request 401 cùng lúc không gọi refresh nhiều lần?