I've conducted hundreds of Angular interviews over 12 years in fintech. The same mistakes keep appearing. Senior developers with 5+ years of experience trip on the same questions that junior developers struggle with. Not because Angular is hard to use - because Angular is easy to use without understanding how it works.
These five mistakes cost developers job offers. I've seen candidates fail on exactly these points at companies like BNY Mellon, UBS, and major tech firms. Here's how to avoid them.
Mistake #1: Misunderstanding Change Detection and OnPush
This is the most common interview failure point. A candidate explains they've used Angular for years, then can't explain why their OnPush component stopped updating.
The Mistake
@Component({ selector: 'app-user-list', template: ` <div *ngFor="let user of users">{{ user.name }}</div> <button (click)="addUser()">Add User</button> `, changeDetection: ChangeDetectionStrategy.OnPush})export class UserListComponent { @Input() users: User[] = []; addUser() { // This WILL NOT update the view! this.users.push({ id: 99, name: 'New User' }); }}
When asked "Why isn't the view updating?", weak answers include:
"Maybe there's a bug?"
"I'd need to see the full code"
"Change detection must be broken"
The Strong Answer
"OnPush change detection uses reference equality (===) to check if inputs changed. When I call push(), I'm mutating the existing array - the reference stays the same. Angular sees the same object reference and skips the component.
The async pipe subscribes when the component renders and unsubscribes when it's destroyed. It also calls markForCheck() automatically, making it perfect with OnPush.
I prefer the async pipe because it's declarative, works with OnPush, and eliminates the possibility of forgetting to unsubscribe."
When You DON'T Need to Unsubscribe
Knowing what doesn't need cleanup shows deeper understanding:
"Some Observables complete naturally and don't need manual unsubscription:
HTTP requests from HttpClient (they complete after one response)
Router events (handled by Angular internally)
Observables created with of() or from() (they complete immediately)
But infinite streams like interval(), fromEvent(), and store selectors always need cleanup."
Mistake #3: Confusion About Dependency Injection Scopes
"How do you ensure a service is a singleton?" This question reveals whether you understand Angular's injector hierarchy.
The Mistake
// Candidate says: "I add it to providers"@NgModule({ providers: [UserService] // But which injector?})export class UsersModule { }
Then asked "What if UsersModule is lazy-loaded?" - silence.
The Strong Answer
"Angular has a hierarchical injector system. Where you provide a service determines its scope:
1. Root singleton (recommended):
@Injectable({ providedIn: 'root' })export class UserService { }
This creates exactly one instance for the entire application, regardless of where it's injected. It also enables tree-shaking - if the service isn't used, it's removed from the bundle.
2. Module-level provider:
@NgModule({ providers: [UserService]})export class UsersModule { }
If UsersModule is eagerly loaded, UserService goes to the root injector (singleton).
If UsersModule is lazy-loaded, a new child injector is created. The service becomes a singleton within that lazy-loaded module only.
3. Component-level provider:
@Component({ providers: [UserService]})export class UserComponent { }
Every instance of UserComponent gets its own UserService instance. The service is destroyed with the component."
The Follow-Up Trap
"What if you need to inject a value that isn't a class?"
"I use InjectionToken for non-class values:
export const API_URL = new InjectionToken<string>('apiUrl');// In moduleproviders: [ { provide: API_URL, useValue: 'https://api.example.com' }]// In serviceconstructor(@Inject(API_URL) private apiUrl: string) { }
InjectionToken is type-safe and prevents the magic string problems of the old string-based injection."
Mistake #4: Misusing Lifecycle Hooks
"What's the difference between the constructor and ngOnInit?" This fundamental question trips up surprisingly many candidates.
The Mistake
@Component({ selector: 'app-user', template: `<div>{{ userData?.name }}</div>`})export class UserComponent { @Input() userId!: number; userData: User; constructor(private userService: UserService) { // MISTAKE: Input isn't set yet! this.userService.getUser(this.userId).subscribe( user => this.userData = user ); }}
Weak answer: "ngOnInit is just where Angular wants you to put initialization code."
The Strong Answer
"The constructor and ngOnInit serve different purposes:
Constructor:
Called by JavaScript, not Angular
@Input properties are NOT set yet
Only use for dependency injection
Keep it simple - no initialization logic
ngOnInit:
Called by Angular after setting @Input properties
First change detection has run
This is where initialization logic belongs
export class UserComponent implements OnInit { @Input() userId!: number; constructor(private userService: UserService) { // userId is undefined here } ngOnInit() { // userId is now available this.loadUser(); }}
The lifecycle order matters:
Constructor
ngOnChanges (first call, inputs are set)
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterViewInit
... (repeated on changes)
ngOnDestroy"
The Senior-Level Extension
"Understanding the full lifecycle becomes critical for complex components:
ngOnChanges: Called before ngOnInit and whenever @Input values change. Receives a SimpleChanges object with previous and current values.
ngAfterViewInit: Safe to access @ViewChild references here, not before. A common mistake is trying to access view children in ngOnInit.
ngAfterContentInit: Safe to access @ContentChild references (projected content).
@Component({...})export class ChartComponent implements AfterViewInit { @ViewChild('canvas') canvas!: ElementRef<HTMLCanvasElement>; ngOnInit() { // this.canvas is undefined! } ngAfterViewInit() { // this.canvas is now available this.initChart(); }}```"
Mistake #5: Ignoring Performance Best Practices
"How would you optimize an Angular application?" This open-ended question separates those who've dealt with real performance issues from those who haven't.
The Mistake
A candidate mentions "use OnPush" but can't explain specific optimizations or why they matter.
The Strong Answer
"I focus on these key areas:
1. Never call methods in templates:
// BAD - formatDate() runs on every change detectiontemplate: `<div>{{ formatDate(user.createdAt) }}</div>`// GOOD - Pure pipe only recalculates when input changestemplate: `<div>{{ user.createdAt | date:'medium' }}</div>`
Methods execute every change detection cycle. In an app checking 500 components, that's 500 function calls per user interaction.
2. Always use trackBy with ngFor:
<div *ngFor="let item of items; trackBy: trackById"> {{ item.name }}</div>trackById(index: number, item: Item): number { return item.id;}
Without trackBy, Angular destroys and recreates all DOM elements when the array changes. With trackBy, it only updates elements that actually changed.
"Walk me through diagnosing a slow Angular application."
"I follow this process:
Profile with Chrome DevTools - Look at the Performance tab for long frames
Check change detection frequency - Add console.log to templates. If it fires constantly, something's triggering unnecessary checks
Use Angular DevTools - The profiler shows exactly which components are checking and how long each takes
Look for common culprits:
Methods or getters in templates
Missing trackBy in ngFor loops
Components not using OnPush
Subscriptions firing too frequently
Bundle analysis - Run ng build --stats-json and use webpack-bundle-analyzer to find oversized dependencies
The fix is usually one of: add OnPush, add trackBy, convert method to pipe, or lazy load a module."
Bonus: The Question That Reveals Everything
After discussing these specifics, interviewers often ask: "If you were building a new Angular application today, what patterns would you establish from day one?"
This is your chance to show architectural thinking:
"I'd establish these patterns:
OnPush by default - Create a schematic that generates components with OnPush
Async pipe everywhere - Ban manual subscriptions in templates. Use the async pipe and handle loading/error states declaratively
Smart/dumb component pattern - Container components handle data fetching, presentational components only receive @Input and emit @Output
Centralized error handling - HTTP interceptor for API errors, global error handler for unexpected exceptions
Strict TypeScript - Enable strictNullChecks, noImplicitAny, strictPropertyInitialization. Catch bugs at compile time
Lazy loading from the start - Define feature module boundaries early. It's harder to add lazy loading later
These patterns prevent the performance and maintainability issues that make Angular applications hard to work with at scale."
Quick Reference: What to Say (and Not Say)
Topic
Weak Answer
Strong Answer
OnPush not updating
"Change detection is broken"
"Mutation doesn't change reference - use spread operator"
Memory leaks
"I unsubscribe somewhere"
"Async pipe is preferred, or takeUntil pattern"
Service singleton
"Add to providers"
"providedIn: 'root' for tree-shakeable singleton"
Constructor vs ngOnInit
"ngOnInit is Angular's way"
"Constructor: DI only. ngOnInit: inputs are set"
Performance
"Use OnPush"
"TrackBy, pure pipes, lazy loading, avoid template methods"
Practice Before Your Interview
Go through each mistake and make sure you can:
Recognize the problem in code
Explain why it's wrong (the underlying mechanism)
Show the fix with correct code
Discuss trade-offs when there are multiple solutions
The developers who get offers aren't necessarily the ones who've memorized the most. They're the ones who can diagnose problems and explain their reasoning clearly.
Related Articles
If you found this helpful, check out these related guides:
Written by the EasyInterview team, based on real interview experience from 12+ years in tech and hundreds of technical interviews conducted at companies like BNY Mellon, UBS, and leading fintech firms.
Ready to ace your interview?
Get 550+ interview questions with detailed answers in our comprehensive PDF guides.