54 questions - Beginner to advanced

Angular interview questions and answers

Angular interviews go deeper than React ones because the framework has more built-in parts. The questions that decide the result are usually change detection, dependency injection, RxJS in services, and forms. Everything below is in plain English.

Angular basics

What is Angular?

Angular is a complete frontend framework from Google, written in TypeScript. Unlike a library, it already includes routing, HTTP, forms, dependency injection and testing, so a large team does not have to choose and glue those pieces together.

What is the difference between AngularJS and Angular?

AngularJS is the old 1.x version written in JavaScript, using scopes, controllers and dirty checking. Angular from version 2 onwards is a complete rewrite in TypeScript with components, a proper dependency injection system and much better performance. They are not compatible.

What is a component?

A component is one piece of the screen: a TypeScript class for the logic, an HTML template for the view, and CSS for the style, tied together by the @Component decorator. Every Angular app is a tree of components starting at the root.

@Component({
  selector: "app-user-card",
  standalone: true,
  template: `<h3>{{ name }}</h3>`,
})
export class UserCardComponent {
  @Input() name = "";
}

What is a module (NgModule)?

An NgModule groups components, directives, pipes and providers that belong together and declares what they can use and what they expose. Modern Angular prefers standalone components, where each component lists its own imports, so NgModules are becoming optional.

What is a standalone component?

A component that does not belong to any NgModule. It sets standalone: true and imports whatever it needs directly. It removes a whole layer of boilerplate and makes lazy loading a single component possible.

What is a directive and what types are there?

A directive adds behaviour to an existing element. Structural directives change the DOM layout and start with a star, like *ngIf and *ngFor. Attribute directives change appearance or behaviour, like ngClass and ngStyle. A component is technically a directive with a template.

What is data binding in Angular?

There are four kinds. Interpolation {{ value }} puts data in the template. Property binding [prop] passes data down. Event binding (click) sends events up. Two-way binding [(ngModel)] does both at once and is just the other two combined.

<input [value]="name" (input)="name = $event.target.value" />
<!-- same as -->
<input [(ngModel)]="name" />

What is the difference between a constructor and ngOnInit?

The constructor runs when the class is created and should only be used for dependency injection. ngOnInit runs after Angular has set the input properties, so that is where you read inputs and start your setup work.

What are the lifecycle hooks in order?

ngOnChanges when an input changes, ngOnInit once after the first inputs, ngDoCheck on every check, ngAfterContentInit and ngAfterContentChecked for projected content, ngAfterViewInit and ngAfterViewChecked for the view and child views, and ngOnDestroy just before the component is removed.

What do you do in ngOnDestroy?

Clean up: unsubscribe from manual subscriptions, clear intervals, remove event listeners and disconnect observers. Skipping this is the most common cause of memory leaks in Angular apps.

What is content projection and ng-content?

It lets a parent pass markup into a child component template, which is Angular version of React children. Use a select attribute to project different pieces into different slots.

<!-- card.component.html -->
<div class="card">
  <header><ng-content select="[card-title]"></ng-content></header>
  <ng-content></ng-content>
</div>

What is the difference between ng-template, ng-container and ng-content?

ng-template holds markup that is not rendered until something asks for it - structural directives use it. ng-container is an invisible grouping element that lets you apply a directive without adding a real DOM node. ng-content is the slot where a parent projected content appears.

What is the AsyncPipe and why is it recommended?

It subscribes to an Observable in the template, shows the latest value, and unsubscribes automatically when the component is destroyed. That removes a whole class of memory leak bugs, so it is the preferred way to consume observables in a view.

<div *ngIf="user$ | async as user">{{ user.name }}</div>

Dependency injection and services

What is dependency injection?

Instead of a class creating the things it needs, Angular creates them and passes them in. That makes classes easier to test, because you can pass a fake service, and easier to reuse, because the class does not care where the dependency came from.

@Injectable({ providedIn: "root" })
export class UserService {
  constructor(private http: HttpClient) {}
}

// in a component
constructor(private users: UserService) {}
// or the modern form
private users = inject(UserService);

What does providedIn: "root" mean?

The service is registered once for the whole application and one shared instance is created the first time something injects it. It is also tree-shakable - if nothing uses the service, it is dropped from the bundle.

What is the difference between providing a service in root and in a component?

In root there is one instance for the whole app, so state is shared. Provided in a component, a new instance is created for each instance of that component and destroyed with it, which is useful for per-form or per-widget state.

What is an injection token?

A unique key used to inject something that is not a class, such as a configuration object or a string. You create it with new InjectionToken and provide a value for it.

export const API_URL = new InjectionToken<string>("API_URL");
// provide: { provide: API_URL, useValue: "https://api.example.com" }

What is the difference between useClass, useValue, useFactory and useExisting?

useClass instantiates a class, useValue supplies a ready value, useFactory calls a function that builds the value and can depend on other services, and useExisting makes a new token point at an existing provider.

What is an HTTP interceptor?

A piece of code that sees every outgoing request and incoming response. It is where you add an auth token, log timings, show a global loader or retry on failure, without touching each service.

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = inject(AuthService).token;
  return next(req.clone({ setHeaders: { Authorization: "Bearer " + token } }));
};

Why does HttpClient return an Observable and not a Promise?

Because an Observable can be cancelled, retried and combined with operators, and it can emit more than once. Cancelling matters a lot for search-as-you-type, where switchMap drops the previous request automatically.

Do you have to unsubscribe from HttpClient?

HttpClient completes after one value, so it cleans itself up. You should still cancel it when the component is destroyed if the request is long running - the AsyncPipe or takeUntilDestroyed does that for you.

Change detection and performance

The section that separates senior candidates.

What is change detection in Angular?

After anything that could change data - a click, a timer, an HTTP response - Angular walks the component tree and checks whether the values used in each template have changed, then updates the DOM where needed.

What is Zone.js?

A library that patches browser APIs like setTimeout, addEventListener and XHR so Angular knows when something asynchronous has finished and change detection should run. Newer Angular can run zoneless, using signals to know exactly what changed.

What is the difference between Default and OnPush change detection?

With Default, Angular checks the component whenever anything anywhere might have changed. With OnPush, it only checks when an input reference changes, an event fires inside the component, an observable used with the AsyncPipe emits, or you mark it manually. OnPush plus immutable data is the standard performance fix.

@Component({
  selector: "app-row",
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `{{ row.name }}`,
})
export class RowComponent {
  @Input() row!: Row;
}

Why does OnPush break when you mutate an object?

Because OnPush compares input references. If you change a property inside the same object, the reference is identical, so Angular skips the check and the screen does not update. Replace the object instead of mutating it.

What is markForCheck versus detectChanges?

markForCheck marks this component and its ancestors as dirty so they are checked in the next cycle. detectChanges runs change detection on this component immediately. detach stops checking a component altogether.

What is trackBy in *ngFor and why use it?

Without trackBy, Angular identifies list items by object reference, so a refreshed array from the server rebuilds every row. trackBy tells Angular to compare by id, so only the real changes are re-rendered.

<li *ngFor="let user of users; trackBy: trackById">{{ user.name }}</li>

trackById(index: number, user: User) { return user.id; }

Why should you avoid calling a function in a template?

Because it runs on every change detection cycle, which can be hundreds of times a second. Use a pure pipe, a computed signal, or precompute the value in the class.

What is the difference between a pure and an impure pipe?

A pure pipe runs only when its input reference changes, so it is cheap. An impure pipe runs on every change detection cycle, which is slow and should be rare.

What is AOT compilation?

Ahead-of-Time compilation converts templates into JavaScript during the build instead of in the browser. The app starts faster, the bundle is smaller because the compiler is not shipped, and template errors are caught at build time. It is the default for production builds.

How do you make an Angular app faster?

Lazy load feature routes, use OnPush with immutable data, add trackBy to lists, avoid template function calls, virtualise long lists with the CDK, use the AsyncPipe rather than manual subscriptions, and check the bundle with the build analyser.

Forms

What is the difference between template-driven and reactive forms?

Template-driven forms are built in the HTML with ngModel and are quick for small forms, but the logic is hidden in the template. Reactive forms are built in the TypeScript class with FormControl and FormGroup, so they are explicit, easy to test and better for complex or dynamic forms.

form = new FormGroup({
  email: new FormControl("", [Validators.required, Validators.email]),
  password: new FormControl("", Validators.minLength(8)),
});

What is a FormControl, FormGroup and FormArray?

A FormControl is a single field with a value, validation state and events. A FormGroup is an object of controls. A FormArray is a list of controls, used when the user can add rows dynamically.

How do you write a custom validator?

A validator is a function that takes the control and returns null when valid or an object describing the error. An async validator returns an Observable or Promise of the same thing.

export function noSpaces(control: AbstractControl) {
  return control.value?.includes(" ") ? { noSpaces: true } : null;
}

What is the difference between touched, dirty and pristine?

touched means the field has been focused and blurred. dirty means the value has been changed by the user. pristine is the opposite of dirty. Error messages usually show only when the control is invalid and touched or dirty.

What is valueChanges and how do you use it well?

It is an Observable that emits every time the value changes. Combine it with debounceTime and distinctUntilChanged before calling an API, otherwise you fire a request on every keystroke.

this.form.controls.search.valueChanges.pipe(
  debounceTime(300),
  distinctUntilChanged(),
  switchMap((q) => this.api.search(q))
).subscribe();

What is a ControlValueAccessor?

The interface that lets your own component behave like a native form control, so it works with ngModel and formControlName. You implement writeValue, registerOnChange, registerOnTouched and setDisabledState.

What is the difference between setValue and patchValue?

setValue requires every control in the group and throws if one is missing, which catches mistakes. patchValue updates only the keys you supply and ignores the rest.

Routing

How does Angular routing work?

You define an array of routes mapping a path to a component. The router watches the URL and renders the matching component inside <router-outlet>. Order matters, because the first match wins.

export const routes: Routes = [
  { path: "", component: HomeComponent },
  { path: "users/:id", component: UserComponent },
  { path: "**", component: NotFoundComponent },
];

What is lazy loading in Angular?

Loading a feature bundle only when the user navigates to it, using loadComponent or loadChildren. It keeps the first download small, which matters most on slow connections.

{ path: "admin", loadComponent: () => import("./admin/admin.component").then((m) => m.AdminComponent) }

What is a route guard?

A function that runs before navigation and returns true, false or a redirect. CanActivate protects a page, CanDeactivate warns about unsaved changes, and a resolver loads data before the route activates.

export const authGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  return auth.isLoggedIn() || inject(Router).createUrlTree(["/login"]);
};

What is the difference between ActivatedRoute snapshot and observables?

The snapshot gives the value once. The params and queryParams observables keep emitting, which matters when the user navigates from /users/1 to /users/2 and the component is reused rather than recreated.

What is the difference between a route parameter and a query parameter?

A route parameter is part of the path and usually identifies a resource, like /users/42. A query parameter comes after the question mark and usually carries optional filters, like ?page=2&sort=name.

What is a resolver?

A function that fetches data before the route is activated, so the component renders with data already available instead of showing an empty state. The trade-off is that navigation feels slower.

Signals and modern Angular

What is a signal?

A signal is a value that knows who reads it. When it changes, only the places that actually use it are updated - no tree walking. It makes change detection precise and is the basis for zoneless Angular.

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

increment() { this.count.update((c) => c + 1); }

What is the difference between signal, computed and effect?

signal holds a writable value. computed derives a value from other signals and caches it until they change. effect runs side effects when the signals it reads change - it should not be used to set other signals.

What is the difference between a signal and an Observable?

A signal always has a current value you can read synchronously and is meant for state. An Observable is a stream over time that may emit zero or many values and is meant for events and async work. They coexist: toSignal and toObservable convert between them.

What is the new control flow syntax?

Angular now has built-in template blocks - @if, @for, @switch and @defer - that replace *ngIf and *ngFor. They are faster, do not need an import, and @for requires a track expression, which prevents the missing-trackBy performance bug.

@if (user(); as u) {
  <p>{{ u.name }}</p>
} @else {
  <p>Loading...</p>
}

@for (item of items(); track item.id) {
  <li>{{ item.name }}</li>
}

What does @defer do?

It delays loading a block of the template and its JavaScript until a condition is met - the block enters the viewport, the user interacts, or the browser is idle. It is lazy loading at the template level.

What is takeUntilDestroyed?

An RxJS operator from Angular that completes a subscription automatically when the component or service is destroyed, replacing the old destroy$ Subject pattern.

this.service.data$
  .pipe(takeUntilDestroyed())
  .subscribe((data) => this.rows = data);

What is Angular Universal / SSR?

Rendering the app on the server so the browser gets real HTML on first load. It improves perceived speed and SEO. Watch out for code that touches window or document, because those do not exist on the server.

What is ViewChild and ContentChild?

ViewChild gets a reference to an element or component in this component own template, available from ngAfterViewInit. ContentChild gets one from the content projected into it, available from ngAfterContentInit.

How do you share data between unrelated components?

Through a service that holds the state, exposed as a signal or a BehaviorSubject, and injected into both components. For a large app with complex flows, a state library such as NgRx does the same thing with more structure.

How do you test an Angular component?

With TestBed to configure a testing module, then create the component fixture, call detectChanges and assert on the rendered DOM. Replace real services with spies or stubs so tests are fast and deterministic.

Continue with another topic

Practise live

CrackInterviewAI listens to the live interview and gives a structured answer on screen for coding, system design, HR and project questions. Download for Windows.