AngularJSInterview Questions

Angular Interview Questions

Prepare for Angular interviews at all levels — from junior to senior/architect roles. These are the most frequently asked questions, with concise but complete answers.

Fundamentals

Q: What is Angular and how does it differ from AngularJS?

Angular (v2+) is a complete rewrite of AngularJS. Key differences:

  • Angular is built with TypeScript; AngularJS used JavaScript
  • Angular uses a component-based architecture; AngularJS used controllers and scope
  • Angular has unidirectional data flow; AngularJS used two-way binding with $scope
  • Angular is mobile-first and significantly faster with ahead-of-time compilation
  • AngularJS uses dependency injection via strings; Angular uses TypeScript types

Q: What is a Component in Angular?

TS
// A Component is the basic building block of Angular apps.
// It controls a portion of the UI (a view) and consists of:
// 1. TypeScript class (logic)
// 2. HTML template (view)
// 3. CSS styles (styling)
// 4. Metadata via @Component decorator

@Component({
  standalone: true,
  selector: 'app-example',     // How to use it in HTML
  template: '<h1>{{ title }}</h1>',
  styles: ['h1 { color: blue; }']
})
export class ExampleComponent {
  title = 'Hello Angular';
}

Q: What is the difference between a Component and a Directive?

Feature

Component

Directive

Template

Yes — has its own template

No template

Selector

Usually element: app-hero

Usually attribute: [appHighlight]

Purpose

Create UI building blocks

Add behavior to existing elements

View encapsulation

Yes

No

Examples

AppComponent, UserCard

ngClass, ngIf, appTooltip

Data Binding

Q: What are the types of data binding in Angular?

HTML
<!-- 1. Interpolation — one-way, component → DOM -->
<p>{{ title }}</p>

<!-- 2. Property binding — one-way, component → DOM -->
<input [value]="username" />
<button [disabled]="isLoading" />

<!-- 3. Event binding — one-way, DOM → component -->
<button (click)="onClick()">Click</button>

<!-- 4. Two-way binding — both directions -->
<input [(ngModel)]="username" />
<!-- [(ngModel)] is syntactic sugar for [ngModel]="val" (ngModelChange)="val=$event" -->

Q: What is the difference between [value] and [(value)]?

  • [value] — property binding: data flows one-way from component to DOM
  • [(value)] — two-way binding ("banana in a box"): data flows both ways. It's shorthand for [value]="x" (valueChange)="x = $event"
Services and Dependency Injection

Q: What is Dependency Injection (DI) in Angular?

DI is a design pattern where a class receives its dependencies from an external source rather than creating them itself. Angular's DI system maintains a hierarchy of injectors — root, module-level, and component-level.

When you inject(UserService), Angular traverses the injector tree upward until it finds a provider.

Q: What is the difference between providedIn: 'root' and providing in a component?

TS
// providedIn: 'root' — single singleton instance for the entire app
@Injectable({ providedIn: 'root' })
export class GlobalService {}

// Provided in a component — new instance created per component tree
@Component({
  providers: [LocalService] // Each instance of this component gets its own service instance
})
export class MyComponent {}

Q: What is an Injection Token?

Injection tokens provide a way to inject values that aren't classes (strings, objects, functions):

TS
export const API_URL = new InjectionToken<string>('API_URL');

// Register
providers: [{ provide: API_URL, useValue: 'https://api.example.com' }]

// Inject
const apiUrl = inject(API_URL);
Change Detection

Q: How does Angular's change detection work?

Angular uses Zone.js to intercept asynchronous browser events (click, setTimeout, HTTP). After each event, Angular runs change detection — traversing the component tree top-down and checking if any template bindings have changed. If they have, it updates the DOM.

With OnPush strategy, a component is only checked when:

  1. An input reference changes
  2. An event fires within the component
  3. markForCheck() or detectChanges() is called explicitly
  4. An Observable used with async pipe emits

Q: What are Angular Signals and how do they improve performance?

TS
// Signals provide fine-grained reactivity
// Only the specific DOM nodes reading a signal update when it changes

const count = signal(0);
const doubled = computed(() => count() * 2);

// effect() tracks which signals it reads and re-runs when they change
effect(() => console.log('count is', count()));

// In a component — only the {{count()}} binding updates, not the whole component
@Component({
  template: `<p>{{ count() }}</p><p>{{ otherData }}</p>`,
})
export class SigComponent {
  count = signal(0);
  otherData = 'unchanged'; // Not re-rendered when count changes
}
Routing

Q: What is lazy loading in Angular and why is it important?

Lazy loading defers loading a feature's JavaScript bundle until the user navigates to that route. This reduces the initial bundle size, improving load time and Time to Interactive.

TS
// Without lazy loading — admin bundle loaded even if user never visits /admin
{ path: 'admin', component: AdminComponent }

// With lazy loading — admin bundle downloaded only on /admin navigation
{
  path: 'admin',
  loadComponent: () => import('./admin/admin.component').then(m => m.AdminComponent)
}

Q: What are Route Guards?

Route Guards control navigation. They run before a route is activated and can allow or block navigation:

  • CanActivate — can the user enter this route?
  • CanDeactivate — can the user leave this route (unsaved changes)?
  • CanMatch — should this route even be considered?
  • Resolve — pre-fetch data before activating the route
RxJS

Q: What is the difference between Subject, BehaviorSubject, and ReplaySubject?

Type

Initial Value

Late Subscriber Gets

Common Use

Subject

None

Only future emissions

Events, one-time notifications

BehaviorSubject

Required

Last emitted value

Current state (user, theme)

ReplaySubject(n)

None

Last n emissions

Cache N recent values

AsyncSubject

None

Only the last value on complete

Async operations that complete

Q: What is the difference between switchMap, mergeMap, concatMap, and exhaustMap?

Operator

Behavior

Best For

switchMap

Cancels previous inner observable

Search autocomplete, latest-wins

mergeMap

Runs all in parallel

Independent HTTP requests

concatMap

Queues — waits for each to complete

Sequential operations, file uploads

exhaustMap

Ignores new while previous runs

Login button — prevent double submit

Forms

Q: What is the difference between Template-driven and Reactive forms?

Feature

Template-driven

Reactive

Form logic location

In the HTML template

In the component class

Validation

HTML attributes (required, email)

Validators.required, custom validators

Dynamic forms

Difficult

Easy with FormArray

Unit testing

Requires DOM

No DOM needed — pure class

Complex forms

Gets messy quickly

Scales well

Best for

Simple forms

Complex, dynamic forms

Q: How do you create a custom validator?

TS
// Synchronous custom validator
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export function noSpacesValidator(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const hasSpace = (control.value as string)?.includes(' ');
    return hasSpace ? { noSpaces: { value: control.value } } : null;
  };
}

// Usage
new FormControl('', [Validators.required, noSpacesValidator()])

// Async validator
export function usernameAvailableValidator(userService: UserService): AsyncValidatorFn {
  return (control: AbstractControl): Observable<ValidationErrors | null> => {
    return userService.checkUsername(control.value).pipe(
      map((available) => available ? null : { usernameTaken: true }),
      catchError(() => of(null)),
    );
  };
}
Advanced Topics

Q: What is View Encapsulation in Angular?

Mode

Behavior

Emulated (default)

CSS scoped to component via attribute selectors — styles don't leak

None

Global CSS — styles affect the entire document

ShadowDom

Native browser Shadow DOM — true encapsulation

Q: What is the difference between ngOnInit and the constructor?

  • Constructor — called by JavaScript when the class is instantiated. At this point Angular's DI has injected dependencies, but inputs are not yet set. Avoid logic here, only use for injection.
  • ngOnInit — called by Angular after the first ngOnChanges. Input properties are available. Put initialization logic (API calls, etc.) here.

Q: What is Content Projection?

Content projection lets a component accept external HTML content and render it inside its template using <ng-content>:

HTML
<!-- card.component.html -->
<div class="card">
  <div class="card-header">
    <ng-content select="[slot=header]"></ng-content>
  </div>
  <div class="card-body">
    <ng-content></ng-content>  <!-- Default slot -->
  </div>
</div>

<!-- Usage -->
<app-card>
  <h2 slot="header">Card Title</h2>
  <p>Card body content here</p>
</app-card>

Q: What is the async pipe and what problem does it solve?

The async pipe subscribes to an Observable or Promise and returns the latest value. When the component is destroyed, it automatically unsubscribes — preventing memory leaks. It also calls markForCheck() when a new value arrives, making it work seamlessly with OnPush.

Q: What is AOT compilation?

Ahead-of-Time (AOT) compilation compiles Angular templates to JavaScript at build time rather than in the browser at runtime. Benefits:

  • Faster rendering — no need to compile in the browser
  • Smaller payload — Angular compiler not shipped to client
  • Early template error detection — type errors caught during build
  • Better security — no eval() of template strings at runtime

Angular uses AOT by default since v9 (Ivy).

Signals-Specific Questions

Q: What is the difference between signal() and BehaviorSubject?

Feature

signal()

BehaviorSubject

Read value

count() — call as function

subject.value (synchronous)

Subscribe

effect() or computed()

.subscribe()

Angular template

Native — no pipe needed

Needs | async pipe

Glitch-free

Yes — computed are lazy

No — intermediate states possible

Zone.js required

No

No, but CD integration harder

Best for

Component/service state in Angular 16+

Stream-based state, interop

Scenario-Based Questions

Q: How would you share data between sibling components?

Three approaches:

  1. Parent component — pass data down to both via @Input() and listen for @Output() events
  2. Shared service — inject a shared service with a Signal or BehaviorSubject into both
  3. State management — use NgRx or a signal store for complex shared state

Q: How do you prevent memory leaks when subscribing to Observables?

TS
// Option 1: async pipe (preferred in templates)
// No unsubscribe needed — async pipe handles it

// Option 2: takeUntilDestroyed (Angular 16+, cleanest for class subscriptions)
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

constructor() {
  this.data$.pipe(takeUntilDestroyed()).subscribe(handler);
}

// Option 3: Manual unsubscribe
private destroy$ = new Subject<void>();
ngOnInit() {
  this.data$.pipe(takeUntil(this.destroy$)).subscribe(handler);
}
ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); }
Tip
For senior interviews, also mention the trade-offs between solutions. Showing you know multiple approaches and can choose contextually demonstrates real-world experience over textbook knowledge.