Câu hỏi phỏng vấn vị trí Angular


  • Lời giải: Angular là một Framework mã nguồn mở dựa trên TypeScript để xây dựng ứng dụng Web. Khác với AngularJS (v1.x) dùng JavaScript và cơ chế $scope, Angular (v2+) dựa trên Component, hỗ trợ Mobile tốt hơn và có hiệu năng cao hơn nhờ kiến trúc phân cấp.

  • Code Demo: Cấu trúc một Component cơ bản:

TypeScript
@Component({
  selector: 'app-hello',
  standalone: true,
  template: `<h1>Hello {{name}}</h1>`
})
export class HelloComponent {
  name = 'Angular';
}
  • Lời giải: Là khối xây dựng cơ bản của UI. Một Component bao gồm: Một class TypeScript (xử lý logic), một file HTML (giao diện), một file CSS (định dạng) và Metadata (decorator @Component).

  • Code Demo:

TypeScript
@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent {}
  • Lời giải: Là các component không cần khai báo trong NgModule. Chúng tự quản lý các dependency của mình thông qua mảng imports, giúp code gọn nhẹ và dễ tái sử dụng hơn.

  • Code Demo:

TypeScript
@Component({
  standalone: true,
  imports: [CommonModule, FormsModule],
  selector: 'app-standalone',
  template: `<input [(ngModel)]="name">`
})
export class StandaloneComponent { name = ''; }
  • Lời giải: Có 4 loại chính:

    1. Interpolation: {{ value }} (Từ logic ra UI).

    2. Property Binding: [property]="value" (Gán giá trị cho thuộc tính HTML).

    3. Event Binding: (event)="handler()" (Lắng nghe sự kiện từ UI).

    4. Two-way Binding: [(ngModel)]="value" (Đồng bộ 2 chiều).

  • Code Demo:

HTML
<p>{{ title }}</p>
<img [src]="imageUrl">
<button (click)="save()">Save</button>
<input [(ngModel)]="username">
  • Lời giải: Directive dùng để thay đổi sự xuất hiện hoặc hành vi của các phần tử DOM.

    • Component Directive: Chính là các Component.

    • Structural Directive: Thay đổi cấu trúc DOM (thêm/xóa phần tử), bắt đầu bằng dấu * (ví dụ: *ngIf, *ngFor).

    • Attribute Directive: Thay đổi vẻ ngoài/hành vi (ví dụ: ngClass, ngStyle).

  • Lời giải: Angular 17 giới thiệu cú pháp @if, @for, @switch thay thế cho các Structural Directive cũ, giúp code sạch hơn và hiệu năng tốt hơn.

  • Code Demo:

HTML
@if (isLoggedIn) {
  <p>Welcome!</p>
} @else {
  <button>Login</button>
}

@for (item of items; track item.id) {
  <li>{{ item.name }}</li>
}
  • Lời giải: Dùng để gom nhóm các Component, Directive, Pipe và Service có liên quan lại với nhau thành một khối chức năng. Tuy nhiên, với Standalone Component, vai trò của NgModule đang dần giảm bớt.

  • Lời giải: Dùng để biến đổi dữ liệu ngay trên template trước khi hiển thị cho người dùng.

  • Code Demo:

HTML
<p>{{ birthday | date:'fullDate' }}</p>
<p>{{ price | currency:'VND' }}</p>
  • Lời giải: Sử dụng decorator @Pipe và thực thi interface PipeTransform.

  • Code Demo:

TypeScript
@Pipe({ name: 'square', standalone: true })
export class SquarePipe implements PipeTransform {
  transform(value: number): number {
    return value * value;
  }
}
// Sử dụng: {{ 5 | square }} -> 25
  • Lời giải: Là các class chứa logic nghiệp vụ, dữ liệu hoặc kết nối API được chia sẻ giữa các component. Service giúp tuân thủ nguyên lý DRY (Don't Repeat Yourself).

  • Code Demo:

TypeScript
@Injectable({ providedIn: 'root' })
export class DataService {
  getData() { return ['A', 'B', 'C']; }
}

  • Lời giải: Là một Design Pattern trong đó một class yêu cầu các dependency từ bên ngoài thay vì tự khởi tạo chúng. Angular có một hệ thống DI cực kỳ mạnh mẽ giúp quản lý vòng đời của các service.

  • Code Demo:

TypeScript
constructor(private dataService: DataService) {} // Inject qua constructor
  • Lời giải:

    • 'root': Service là Singleton (duy nhất) cho toàn bộ ứng dụng.

    • Component level: Mỗi instance của component sẽ có một instance service riêng biệt.

  • Lời giải: Là một dòng dữ liệu (stream) mà bạn có thể lắng nghe theo thời gian. Khác với Promise (chỉ trả về 1 giá trị), Observable có thể trả về nhiều giá trị và có thể hủy (unsubscribe).

  • Lời giải: map, filter, switchMap, debounceTime, catchError.

  • Code Demo:

TypeScript
this.searchSubject.pipe(
  debounceTime(300),
  switchMap(term => this.api.search(term))
).subscribe(res => this.results = res);
  • Lời giải: Subject không có giá trị khởi tạo và không phát lại giá trị cũ cho người subcribe mới. BehaviorSubject yêu cầu giá trị khởi tạo và sẽ phát lại giá trị mới nhất ngay khi có người subcribe.

  • Lời giải:

    • ngOnInit: Chạy sau khi component khởi tạo và nhận dữ liệu input.

    • ngOnChanges: Chạy khi các thuộc tính @Input thay đổi.

    • ngOnDestroy: Chạy trước khi component bị hủy (dùng để cleanup).

  • Lời giải: Dùng để truyền dữ liệu giữa cha và con. @Input nhận dữ liệu, @Output phát sự kiện (EventEmitter).

  • Code Demo:

TypeScript
@Input() count: number = 0;
@Output() changed = new EventEmitter<number>();

update() { this.changed.emit(this.count + 1); }
  • Lời giải: Dùng để truy cập trực tiếp vào một phần tử DOM hoặc một Component con từ Component cha.

  • Code Demo:

TypeScript
@ViewChild('myInput') input!: ElementRef;
focus() { this.input.nativeElement.focus(); }
  • Lời giải: Là một cách thức quản lý state mới giúp Angular nhận biết chính xác phần nào của UI cần cập nhật (Fine-grained reactivity), thay vì kiểm tra lại toàn bộ cây component.

  • Code Demo:

TypeScript
count = signal(0);
doubleCount = computed(() => this.count() * 2);

increment() { this.count.update(v => v + 1); }
  • Lời giải: Promise chạy ngay khi khởi tạo, trả 1 giá trị duy nhất. Observable "lười" (chỉ chạy khi subscribe), trả nhiều giá trị theo thời gian và hỗ trợ các toán tử xử lý phức tạp.


  • Lời giải: Chuyển đổi component dựa trên URL của trình duyệt mà không load lại trang. Cần cấu hình mảng Routes và sử dụng <router-outlet>.

  • Lời giải: Dùng để kiểm soát quyền truy cập route (ví dụ: chặn người dùng chưa đăng nhập). Các loại: CanActivate, CanDeactivate, Resolve.

  • Lời giải: Chỉ tải module hoặc component khi người dùng truy cập vào route đó để tối ưu tốc độ ban đầu.

  • Code Demo:

TypeScript
{ path: 'admin', loadChildren: () => import('./admin/admin.routes').then(m => m.ADMIN_ROUTES) }
  • Lời giải:

    • Template-driven: Dựa trên HTML (dùng ngModel), phù hợp form đơn giản.

    • Reactive: Dựa trên TypeScript (dùng FormGroup, FormControl), mạnh mẽ, dễ test, phù hợp form phức tạp.

  • Code Demo:

TypeScript
this.form = new FormGroup({
  email: new FormControl('', [Validators.required, Validators.email]),
  password: new FormControl('', Validators.minLength(6))
});
  • Code Demo:

TypeScript
function forbiddenNameValidator(control: AbstractControl) {
  return control.value === 'admin' ? { forbidden: true } : null;
}
  • Lời giải: Dùng để chặn và sửa đổi các request/response (ví dụ: tự động chèn Token vào Header).

  • Lời giải: Cho phép chèn nội dung HTML từ component cha vào vị trí chỉ định trong component con (tương tự children trong React).

  • Lời giải: Default kiểm tra mọi thay đổi. OnPush chỉ kiểm tra khi @Input thay đổi tham chiếu (reference) hoặc có event phát ra từ chính component đó, giúp tăng hiệu năng cực cao.

  • Lời giải: Dùng để chạy các tác vụ mà không kích hoạt cơ chế Change Detection của Angular (ví dụ: setInterval hoặc thư viện đồ họa nặng).


  • Lời giải: Công cụ hỗ trợ Server-Side Rendering (SSR) cho Angular, giúp SEO tốt và hiển thị trang nhanh hơn.

  • Lời giải: Cách Angular cô lập CSS của component. Có 3 chế độ: Emulated (mặc định), None (ảnh hưởng toàn bộ app), ShadowDom (dùng chuẩn trình duyệt).

  • Lời giải: Tự động subscribe một Observable ngay trên template và tự động unsubscribe khi component bị hủy.

  • Code Demo: <ul><li *ngFor="let user of users$ | async">{{user.name}}</li></ul>

  • Lời giải: Dùng để lấy dữ liệu từ API trước khi chuyển vào một route, giúp trang web hiện ra là có dữ liệu ngay.

  • Lời giải: Sử dụng một Shared Service chứa một Subject hoặc Signal.

  • Lời giải: Giúp Angular xác định đúng phần tử nào trong list thay đổi để chỉ render lại đúng phần tử đó thay vì render lại cả list.

  • Lời giải: Constructor là của class JS, dùng để inject dependency. ngOnInit là của Angular, dùng để thực hiện logic khởi tạo (lúc này @Input mới có giá trị).

  • Lời giải: AOT (Ahead-of-Time) biên dịch lúc build (nhanh, bảo mật hơn). JIT (Just-in-Time) biên dịch lúc chạy trên trình duyệt (dùng cho debug).

  • Lời giải: Dùng Lazy loading, Standalone components, Tree-shaking, và nén ảnh/asset.

  • Lời giải: Là trình biên dịch và render mới (từ bản 9+) giúp Angular build nhanh hơn và file bundle nhỏ hơn nhiều.


  • Lời giải:

    • switchMap: Hủy request cũ nếu có request mới (dùng cho Search).

    • mergeMap: Chạy song song tất cả.

    • concatMap: Chạy tuần tự theo thứ tự.

  • Lời giải: Sử dụng Jasmine (viết code test) và Karma (trình chạy test). Dùng TestBed để cấu hình môi trường test.

  • Lời giải: Một token cho phép chạy một hàm khi ứng dụng đang khởi động (thường dùng để tải cấu hình hệ thống).

  • Lời giải: Cho phép đóng gói Angular Component thành Web Components (Custom Elements) để dùng trong các dự án phi-Angular.

  • Lời giải: Thực thi class ErrorHandler của Angular.

  • Lời giải: Cung cấp kiểu dữ liệu (static typing), tooling tốt, dễ bảo trì cho các dự án cực lớn (Enterprise).

  • Lời giải: Là một function đặc biệt dùng để bổ sung metadata cho class hoặc thuộc tính (ví dụ: @Component, @Directive, @Injectable).

  • Lời giải: Angular có ModuleInjector và ElementInjector. Search theo thứ tự: Component hiện tại -> Cha -> Module -> Root.

  • Lời giải: Cho phép tái sử dụng cấu trúc DOM đã render từ Server thay vì phá đi render lại từ đầu, giúp giảm hiện tượng nháy trang (flickering).

  • Lời giải: Độ dốc học tập (learning curve) cao, dung lượng file bundle ban đầu thường nặng hơn, và tính gò bó cao (opinionated) khiến linh hoạt kém hơn một chút.

Phản hồi từ học viên

5

Tổng 0 đánh giá
Developer Toolbox

TEXT CASE

FORMAT & CLEAN

ENCODE & DECODE

JSON & CRYPTO

Đã sao chép!!!
Gozic - Hệ thống học lập trình, luyện thi, kiểm tra trắc nghiệm trực tuyến uy tín tại Việt Nam.
Hotline: 0967025996
Gozic - Hệ thống học lập trình, luyện thi, kiểm tra trắc nghiệm trực tuyến uy tín tại Việt Nam.