Skip to the solution
EasyFrontend7 min read

What are standalone components?

217 views

The problem

Question presented to candidate: "We are starting a new Angular 22 app. What is a standalone component, why is it the default now, and what does it change about how we bootstrap and lazy load?"

What a strong answer should cover:

  • A standalone component declares its own template dependencies in imports and belongs to no NgModule.
  • Default since v19: the standalone flag is true unless you write standalone: false; the same applies to directives and pipes.
  • Bootstrapping uses bootstrapApplication(App, appConfig), with app-wide providers (provideRouter, provideHttpClient) in appConfig.
  • Lazy loading works per component with loadComponent, no wrapper module needed.
  • Benefits: less boilerplate, dependencies visible per file, better tree-shaking, simpler tests (imports: [Component] in TestBed).
  • Interop with NgModules in both directions, and an automated migration (ng generate @angular/core:standalone).

Clarifying questions expected:

  • "Is there an existing NgModule codebase we need to interoperate with?"
  • "Do you want me to cover lazy loading and providers, or only the component itself?"

Code / implementation expected: Yes β€” a standalone component that imports a pipe, a directive and a child component.

  • standalone
  • modules

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

7 min read Β· 9 sections

Read the code

AngularA standalone component importing a pipe, a directive and a built-in pipe
import { Component, Directive, ElementRef, Pipe, PipeTransform, inject, signal } from "@angular/core";
import { CurrencyPipe } from "@angular/common";

// Three standalone building blocks. None of them sets standalone: true
// because, since Angular 19, that is the default.
@Pipe({ name: "plural" })
export class PluralPipe implements PipeTransform {
  transform(n: number, word: string): string {
    return `${n} ${word}${n === 1 ? "" : "s"}`;
  }
}

@Directive({ selector: "[appHighlight]" })
export class HighlightDirective {
  constructor() {
    inject(ElementRef<HTMLElement>).nativeElement.style.background = "#fff3c4";
  }
}

@Component({
  selector: "cart-line",
  // The component declares its own template dependencies. Nothing else
  // has to know about PluralPipe or CurrencyPipe.
  imports: [PluralPipe, CurrencyPipe, HighlightDirective],
  template: `<p appHighlight>{{ qty() | plural: "item" }} - {{ qty() * 9.5 | currency: "USD" }}</p>
    <button (click)="qty.update(n => n + 1)">add</button>`,
})
export class CartLineComponent {
  qty = signal(1);
}

@Component({
  selector: "app-root",
  imports: [CartLineComponent], // import the component itself, not a module
  template: `<h3>Cart</h3><cart-line />`,
})
export class AppComponent {}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 11 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextEasy

What is the fixture.detectChanges() method in Angular testing, and when should you call it?

Continue