Angular Interview QA
What is Angular?
Angular is a TypeScript-based frontend framework developed by Google. It is used to build single-page applications (SPA) that are fast, modular, and maintainable.
Angular provides:
- High performance: Efficient change detection and rendering
- Modular architecture: Components, modules, services
- Strong tooling: CLI, testing utilities, and debugging tools
- Two-way data binding: Synchronizes data between model and view
- Reactive programming support: Observables and RxJS
It is widely used for enterprise applications, dashboards, and dynamic web apps that require fast updates and rich user experiences.
Architecture of Angular
Angular follows a Component-Based Architecture, which makes applications modular, maintainable, and scalable.
✅ Main Building Blocks of Angular
- Modules (NgModule): Organize the app into cohesive blocks of functionality.
- Components: Define views, templates, and logic for UI elements.
- Templates (HTML): Define the structure and layout of the UI.
- Directives: Modify the DOM structure or behavior of elements.
- Services: Handle business logic, data fetching, and reusable operations.
- Dependency Injection (DI): Provides services to components efficiently.
- Routing: Navigate between views in a single-page application.
- Pipes: Transform data in templates.
📌 Simple Architecture Flow
User interactions are handled in a predictable flow:
User Action → Component → Service → API → Data → Template UI Update
Example Flow:
- User clicks a button
- Component calls a service
- Service calls an API using
HttpClient - API responds with data
- Component updates the UI template
This architecture ensures separation of concerns, modularity, and easier maintenance for large-scale applications.
Components in Angular
A Component is the main UI building block in Angular. Each component encapsulates its own:
- HTML template: Defines the view of the component
- TypeScript logic: The class controlling behavior
- CSS styles: Defines the look and feel
Key Points About Components
- ✅ Each component controls a part of the screen
- ✅ Angular apps are built by combining multiple components
- ✅ Components are reusable
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent {
name: string = 'John Doe';
}
Modules in Angular
A Module is a container that groups related:
- Components
- Directives
- Pipes
- Services
Angular uses modules to organize the application into logical blocks and improve maintainability.
Types of Modules
- ✅ Root Module:
AppModule– Bootstraps the application - ✅ Feature Module:
InvoiceModule, AdminModule– Encapsulates a specific feature - ✅ Shared Module: Contains common components, pipes, directives used across the app
- ✅ Core Module: Contains singleton services and app-wide providers
@NgModule({
declarations: [UserComponent],
imports: [CommonModule],
exports: [UserComponent]
})
export class SharedModule {}
Data Binding in Angular
Data Binding is the communication between:
- Component (TypeScript)
- Template (HTML)
Types of Data Binding
1️⃣ Interpolation (One-way: TS → HTML)
Hello {{ name }}
2️⃣ Property Binding (One-way: TS → HTML)
3️⃣ Event Binding (One-way: HTML → TS)
4️⃣ Two-Way Binding (TS ↔ HTML)
You typed: {{ username }}
Summary Table of Data Binding
| Binding Type | Direction | Example |
|---|---|---|
| Interpolation | TS → HTML | {{name}} |
| Property Binding | TS → HTML | [value]="data" |
| Event Binding | HTML → TS | (click)="do()" |
| Two-way Binding | Both | [(ngModel)]="name" |
Difference Between Component and Directive
✅ Component
- A component is a directive with a template
- Used to build UI blocks (header, login, dashboard)
- Has:
- HTML template
- CSS styles
- TypeScript logic
✅ Directive
- A directive does not have its own UI template
- Used to change behavior or appearance of an element
- Example:
ngIf,ngFor,ngClass
Feature Comparison Table
| Feature | Component | Directive |
|---|---|---|
| Template | ✅ Yes | ❌ No |
| Purpose | UI block | Modify behavior/style |
| Example | Navbar, Login | Highlight, Hide, Validation |
Angular Pipes
In Angular, Pipes are used to transform data before displaying it in the template. Pipes take input data, process it, and return a formatted output. They help keep templates clean, readable, and maintainable.
What is a Pipe in Angular?
A Pipe in Angular is a simple way to transform values such as strings, dates, numbers, or asynchronous data directly in the template.
{{ expression | pipeName }}
Why Use Pipes?
- Improve code readability
- Reuse transformation logic
- Keep component logic clean
- Format data directly in templates
Types of Pipes in Angular (By Origin)
Angular provides two main types of pipes:
1. Built-in Pipes
These pipes are provided by Angular out of the box.
- DatePipe – Formats date values
- UpperCasePipe – Converts text to uppercase
- LowerCasePipe – Converts text to lowercase
- TitleCasePipe – Converts text to title case
- CurrencyPipe – Formats currency values
- DecimalPipe – Formats decimal numbers
- PercentPipe – Formats percentages
- SlicePipe – Extracts a subset of a string or array
- JsonPipe – Converts objects into JSON format
- AsyncPipe – Handles Observables and Promises
2. Custom Pipes
Custom pipes are created by developers to perform application-specific
data transformations using the @Pipe decorator.
Creating a Custom Pipe in Angular
Custom pipes allow you to create reusable data transformation logic based on your application needs.
Steps to Create a Custom Pipe
- Create a pipe using CLI:
ng generate pipe pipeNameor manually - Implement the PipeTransform interface
- Define the transform() method
- Return the transformed data
@Pipe({ name: 'customPipe' })
export class CustomPipe implements PipeTransform {
transform(value: any): any {
return value;
}
}
Example: Filter Array of Strings
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'filter' })
export class FilterPipe implements PipeTransform {
transform(items: string[], searchText: string): string[] {
if (!items || !searchText) return items;
return items.filter(item =>
item.toLowerCase().includes(searchText.toLowerCase())
);
}
}
Usage
<li *ngFor="let name of names | filter:search">
{{ name }}
</li>
Example: Reverse a String
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
transform(value: string): string {
return value.split('').reverse().join('');
}
}
Usage
<p>{{ 'Angular' | reverse }}</p>
<!-- Output: ralugnA -->
Example: Capitalize First Letter
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'capitalize' })
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
return value.charAt(0).toUpperCase() +
value.slice(1).toLowerCase();
}
}
Usage
<p>{{ 'hello world' | capitalize }}</p>
<!-- Output: Hello world -->
Example: Email Validation Pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'emailCheck' })
export class EmailCheckPipe implements PipeTransform {
transform(value: string): boolean {
if (!value) return false;
const emailRegex =
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return emailRegex.test(value);
}
}
Usage
<p>Valid Email: {{ email | emailCheck }}</p>
Usage with *ngIf
<p *ngIf="email | emailCheck; else invalid"> Email is valid </p> <ng-template #invalid> Email is invalid </ng-template>
Async Pipe in Angular
The AsyncPipe is a built-in Angular pipe used to handle asynchronous data streams such as Observables and Promises.
- Automatically subscribes to data
- Automatically unsubscribes on component destroy
- Prevents memory leaks
{{ users$ | async }}
Pipe Chaining in Angular
Pipe Chaining allows multiple pipes to be applied sequentially. The output of one pipe becomes the input of the next pipe.
{{ today | date:'fullDate' | uppercase }}
Pipe chaining is a usage concept, not a separate type of pipe.
Types of Pipes by Behavior
Angular pipes can also be classified based on how they respond to change detection.
Pure Pipes
- Default behavior
- Executed only when input value changes
- Better performance
Examples: DatePipe, UpperCasePipe, DecimalPipe
Impure Pipes
- Executed on every change detection cycle
- Lower performance
- Used when data mutates without reference change
@Pipe({
name: 'impurePipe',
pure: false
})
AsyncPipe is an example of a built-in impure pipe.
Complete Classification of Angular Pipes
| Concept | Category |
|---|---|
| Built-in Pipe | By Origin |
| Custom Pipe | By Origin |
| Pure Pipe | By Behavior |
| Impure Pipe | By Behavior |
| AsyncPipe | Built-in + Impure |
| Pipe Chaining | Template Usage Concept |
Conclusion
Angular Pipes provide a powerful and clean way to format and transform data directly in templates. Understanding built-in pipes, custom pipes, async pipe, pure vs impure behavior, and pipe chaining helps in writing efficient and maintainable Angular applications.
Important Notes
- Custom pipes are pure by default
- Use impure pipes carefully due to performance impact
- Avoid heavy logic inside pipes
- Pipes are best suited for formatting and transformation
Summary
- Custom pipes allow reusable data transformation
- They are easy to create and use in templates
- Common examples include filtering, formatting, validation
- Email validation can also be handled using custom pipes
Custom pipes in Angular are used to create reusable transformation logic that formats or modifies data directly in templates.
What is an Observable?
An Observable is a stream of data that can emit multiple values over time. To receive the emitted values, you must subscribe to it.
Key Characteristics of Observables
-
Supports multiple values
An Observable can emit zero, one, or many values over time. -
Lazy execution
An Observable starts executing only when someone subscribes to it. -
Can be canceled (unsubscribed)
You can stop receiving data by unsubscribing, which helps prevent memory leaks.
Example of an Observable
import { Observable } from 'rxjs';
const observable = new Observable(observer => {
observer.next('Hello');
observer.next('World');
});
Observable in Angular Templates
In Angular templates, Observables are commonly used with the AsyncPipe, which automatically subscribes and unsubscribes.
{{ data$ | async }}
What is a Promise?
A Promise represents a single asynchronous result that may succeed (resolve) or fail (reject) in the future. Once resolved or rejected, a Promise cannot emit another value.
Use Cases of Promise
- HTTP requests (older JavaScript/TypeScript code)
- Async tasks such as file reading, timers, or API calls
- When only one result is required
Example of a Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data loaded');
}, 1000);
});
promise.then(result => console.log(result));
.catch(err => console.error(err));
Difference Between Observable and Promise
| Feature | Observable | Promise |
|---|---|---|
| Values | Can emit multiple values over time | Emits a single value |
| Lazy / Eager | Lazy (executes only on subscription) | Eager (executes immediately) |
| Cancelable | Yes, can unsubscribe | No, cannot cancel |
| Operators | Supports RxJS operators (map, filter, debounce) | No operators |
| Use Case | Real-time data, streams, events, WebSockets | Single async operation |
A Promise handles a single asynchronous value, while an Observable can emit multiple values over time and supports cancellation and powerful operators.
What are Directives in Angular?
Directives are special classes in Angular that are used to manipulate the DOM. They can change the appearance, behavior, or structure of elements in a template.
Directives do not render their own view; instead, they modify the behavior or structure of existing DOM elements.
Types of Directives in Angular
1. Structural Directives
Structural directives change the DOM structure by adding or removing elements. They are prefixed with an asterisk (*) in templates.
Examples of Structural Directives
- *ngIf – Conditionally renders elements
- *ngFor – Iterates over a list of items
- *ngSwitch – Displays elements based on switch cases
Example
<div *ngIf="isLoggedIn">Welcome User</div>
<li *ngFor="let item of items">{{ item }}</li>
2. Attribute Directives
Attribute directives change the appearance or behavior of an element without changing the DOM structure.
Examples of Attribute Directives
- ngClass – Dynamically add or remove CSS classes
- ngStyle – Dynamically change inline styles
- Custom Attribute Directives
Example
<div [ngClass]="{'active': isActive}">Active Item</div>
<div [ngStyle]="{'color': 'red'}">Styled Text</div>
Custom Attribute Directive Example
Below is an example of a custom attribute directive that highlights an element when the mouse enters and removes the highlight when the mouse leaves.
import { Directive, ElementRef, Renderer2, HostListener } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(
private el: ElementRef,
private renderer: Renderer2
) {}
@HostListener('mouseenter')
onMouseEnter() {
this.renderer.setStyle(
this.el.nativeElement,
'background-color',
'yellow'
);
}
@HostListener('mouseleave')
onMouseLeave() {
this.renderer.setStyle(
this.el.nativeElement,
'background-color',
'white'
);
}
}
Usage
<p appHighlight>Hover over me</p>
Summary
- Directives manipulate the DOM in Angular
- Structural directives modify DOM structure
- Attribute directives modify appearance or behavior
- Custom directives allow reusable DOM behavior
@Input() and @Output() in Angular
✅ @Input()
Used to receive data from parent → child component.
Parent Component:
<app-child [name]="userName"></app-child>
Child Component:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: '<p>Hello {{ name }}</p>'
})
export class ChildComponent {
@Input() name!: string;
}
✅ @Output()
Used to send data/events from child → parent component.
Child Component:
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: '<button (click)="send()">Send</button>'
})
export class ChildComponent {
@Output() notify = new EventEmitter<string>();
send() {
this.notify.emit("Hello Parent!");
}
}
Parent Component:
<app-child (notify)="getMessage($event)"></app-child>
Difference Between Pure and Impure Pipes
✅ Pure Pipe (default)
- Runs only when input reference changes
- Faster and best for performance
@Pipe({ name: 'myPipe', pure: true })
✅ Impure Pipe
- Runs on every change detection
- Slower, use only when needed
@Pipe({ name: 'myPipe', pure: false })
🔥 Key Difference
| Feature | Pure Pipe | Impure Pipe |
|---|---|---|
| Execution | Only when value changes | Every change detection |
| Performance | ✅ Fast | ❌ Slower |
| Use case | Formatting, filtering stable data | Filtering dynamic/mutating arrays |
Dependency Injection (DI) in Angular
Dependency Injection is a design pattern where Angular automatically provides required objects (services) instead of creating them manually using new.
Example
constructor(private userService: UserService) {}
✅ Benefits of DI
- Reusability
- Loose coupling
- Easy testing
- Clean architecture
Different Ways to Provide a Service in Angular
1️⃣ Using providedIn: 'root'
@Injectable({ providedIn: 'root' })
export class UserService {}
2️⃣ Provide in AppModule
@NgModule({
providers: [UserService]
})
export class AppModule {}
3️⃣ Provide in a Feature Module
@NgModule({
providers: [UserService]
})
export class AdminModule {}
4️⃣ Provide in a Component
@Component({
providers: [UserService]
})
export class DashboardComponent {}
Difference Between providedIn: 'root' and providers Array
- providedIn: 'root'
- Singleton service across the entire app
- Tree-shakable (unused services removed during build)
- Recommended approach
- providers array
- Can create multiple instances depending on where you provide it:
- AppModule → singleton
- Feature Module → scoped
- Component → new instance per component
Angular Routing
Angular Routing allows navigation between different views/pages without reloading the page (SPA).
Example
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'login', component: LoginComponent }
];
Lazy Loading
Lazy Loading means loading feature modules only when required, instead of loading everything at app start.
✅ Benefits
- Faster initial load
- Better performance
- Smaller bundle size
Example
const routes: Routes = [
{
path: 'admin',
loadChildren: () =>
import('./admin/admin.module').then(m => m.AdminModule)
}
];
Difference Between RouterModule.forRoot() and RouterModule.forChild()
✅ forRoot()
- Used only once in the root module (
AppModule) - Creates the main router service
- Registers app-level routes
RouterModule.forRoot(routes)
✅ forChild()
- Used in feature modules
- Adds additional routes to the router
- Used in lazy-loaded modules
RouterModule.forChild(adminRoutes)
🔥 Key Difference Table
| Feature | forRoot() | forChild() |
|---|---|---|
| Used in | AppModule | Feature Module |
| Router service | Creates it | Uses existing |
| Times used | Only once | Many times |
ViewEncapsulation in Angular
ViewEncapsulation controls how Angular applies CSS styles to components. By default, Angular scopes component styles to that component only, not globally.
Types of ViewEncapsulation
1️⃣ Emulated (Default)
- Styles apply only to that component
- Angular adds unique attributes like
_ngcontent-xxx encapsulation: ViewEncapsulation.Emulated- ✅ Most commonly used
2️⃣ None
- Styles become global
- Can affect other components too
encapsulation: ViewEncapsulation.None- Use for global styling (rare)
3️⃣ ShadowDom
- Uses real browser Shadow DOM
- Styles are strictly isolated
encapsulation: ViewEncapsulation.ShadowDom- Use when true Shadow DOM behavior is needed
Guards in Angular
Guards control access to routes and decide whether navigation should be allowed or blocked.
Common Guard Types
- ✅ CanActivate: Allow/deny entering a route
- ✅ CanDeactivate: Allow/deny leaving a route
- ✅ CanLoad: Allow/deny lazy-loaded module loading
- ✅ Resolve: Fetch data before route loads
Example: CanActivate Guard
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(): boolean {
const isLoggedIn = !!localStorage.getItem("token");
if (!isLoggedIn) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
Usage:
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }
HttpClient in Angular
Angular’s HttpClient is a built-in service to call APIs.
Import it via:
import { HttpClientModule } from '@angular/common/http';
Key Points
- ✅ Returns an Observable
- ✅ Supports GET, POST, PUT, DELETE
- ✅ Supports interceptors, headers, and error handling
- ✅ Works with RxJS operators like
map,catchError,retry
Example: GET API call
constructor(private http: HttpClient) {}
getUsers() {
return this.http.get<User[]>("https://api.com/users");
}
// Component usage
this.getUsers().subscribe(data => {
console.log(data);
});
How it Works Internally
- Component calls service method
- Service uses HttpClient
- HttpClient sends request through interceptors
- Server responds
- Observable emits response
- Component receives it via
subscribeorasync pipe
RxJS Subjects in Angular
1️⃣ Subject
- Does NOT store old values
- Subscribers receive values only after subscribing
import { Subject } from 'rxjs';
const sub = new Subject<number>();
sub.next(1);
sub.subscribe(x => console.log("Subscriber A:", x));
sub.next(2);
sub.next(3);
// Output:
// Subscriber A: 2
// Subscriber A: 3
Best Use Case: Button clicks, notifications, trigger events
2️⃣ BehaviorSubject
- Stores the latest value
- Requires an initial value
- New subscribers immediately get the last emitted value
import { BehaviorSubject } from 'rxjs';
const bsub = new BehaviorSubject<number>(0);
bsub.subscribe(x => console.log("Subscriber A:", x));
bsub.next(10);
bsub.next(20);
bsub.subscribe(x => console.log("Subscriber B:", x));
// Output:
// Subscriber A: 0, 10, 20
// Subscriber B: 20
Best Use Case: Logged-in user data, cart count, theme mode, shared state
3️⃣ ReplaySubject
- Stores multiple previous values and replays them to new subscribers
- You can specify how many values to store
import { ReplaySubject } from 'rxjs';
const rsub = new ReplaySubject<number>(2);
rsub.next(1);
rsub.next(2);
rsub.next(3);
rsub.subscribe(x => console.log("Subscriber A:", x));
// Output:
// Subscriber A: 2
// Subscriber A: 3
Best Use Case: Chat messages, audit logs, history tracking
🔥 Final Comparison Table
| Feature | Subject | BehaviorSubject | ReplaySubject |
|---|---|---|---|
| Stores values | ❌ No | ✅ Latest | ✅ Multiple |
| Needs initial value | ❌ No | ✅ Yes | ❌ No |
| Late subscribers get old values | ❌ No | ✅ Last one | ✅ Multiple |
| Use case | Events (clicks, triggers) | Shared state (login user, cart count) | History/data replay |
Real Angular Use Case: BehaviorSubject for Login State
private user$ = new BehaviorSubject<string | null>(null);
setUser(name: string) {
this.user$.next(name);
}
getUser() {
return this.user$.asObservable();
}
💡 One-Liner Summary
- ✅ Subject → event stream, no memory
- ✅ BehaviorSubject → state stream, remembers last value
- ✅ ReplaySubject → remembers multiple previous values
What are Angular Lifecycle Hooks?
Answer:
Angular Lifecycle Hooks are special methods that allow developers to tap into different stages of a component or directive’s lifecycle—creation, rendering, change detection, and destruction. They help manage initialization, data updates, DOM access, and cleanup in a structured way.
List all Angular lifecycle hooks.
Answer:
- ngOnChanges – called when @Input() properties change.
- ngOnInit – called once after first ngOnChanges.
- ngDoCheck – called during every change detection cycle.
- ngAfterContentInit – called after projected <ng-content> content is initialized.
- ngAfterContentChecked – after every check of projected content.
- ngAfterViewInit – after component’s view and child views are initialized.
- ngAfterViewChecked – after every check of component view.
- ngOnDestroy – called just before component/directive is destroyed.
What is the difference between constructor and ngOnInit?
Answer:
- Constructor: Runs first, only used for dependency injection. Inputs are not yet available.
- ngOnInit: Runs after first ngOnChanges. Used to initialize data, call APIs, set up forms, etc.
What is ngOnChanges and when is it used?
Answer:
- Triggered whenever an @Input() property changes.
- Receives a SimpleChanges object with previousValue and currentValue.
- Used to react to parent data changes dynamically.
@Input() userId: number;
ngOnChanges(changes: SimpleChanges) {
if (changes['userId']) {
this.loadUser(changes['userId'].currentValue);
}
}
What is ngDoCheck? When should it be used?
Answer:
- Called on every change detection cycle.
- Used for custom change detection, like detecting mutations in arrays or objects that Angular doesn’t automatically detect.
- ⚠️ Use sparingly; frequent execution can affect performance.
Explain ngAfterContentInit and ngAfterContentChecked.
Answer:
- ngAfterContentInit: Called once after <ng-content> is projected into the component.
- ngAfterContentChecked: Called every change detection for projected content.
- Use cases: Access or validate dynamic content from parent components.
Explain ngAfterViewInit and ngAfterViewChecked.
Answer:
-
ngAfterViewInit: Called once after the component view and child views are fully initialized.
- Use for accessing @ViewChild or @ViewChildren.
-
ngAfterViewChecked: Called after every change detection of the component view.
- Use for post-render updates (charts, tables, or dynamic DOM manipulations).
What is ngOnDestroy and why is it important?
Answer:
- Called just before a component is destroyed.
- Used for cleanup tasks such as unsubscribing from observables, clearing timers, or removing event listeners.
- Enterprise importance: Prevents memory leaks in large applications.
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
clearInterval(this.timer);
}
Can hooks be used in directives?
Answer:
Yes. Directives also have lifecycle hooks.
@Directive({ selector: '[appHighlight]' })
export class HighlightDirective implements OnInit, OnDestroy {
constructor(private el: ElementRef) {}
ngOnInit() {
this.el.nativeElement.style.backgroundColor = 'yellow';
}
ngOnDestroy() {
this.el.nativeElement.style.backgroundColor = '';
}
}
What is the order of Angular lifecycle hooks?
Answer:
- constructor()
- ngOnChanges()
- ngOnInit()
- ngDoCheck()
- ngAfterContentInit()
- ngAfterContentChecked()
- ngAfterViewInit()
- ngAfterViewChecked()
- ngOnDestroy()
Enterprise Tip: This order is essential when debugging complex component interactions.
Difference between ngOnChanges and ngDoCheck?
| ngOnChanges | ngDoCheck |
|---|---|
| Triggered only for @Input() changes | Triggered on every change detection cycle |
| Receives SimpleChanges | No parameters; must manually detect changes |
| Automatically detects primitive/object input changes | Used for custom detection logic |
| Runs before ngOnInit | Runs multiple times after ngOnInit |
Can hooks be combined in a component?
Answer:
Yes. Enterprise apps often use multiple hooks together:
- ngOnChanges → React to parent input changes
- ngOnInit → Fetch initial data
- ngAfterViewInit → Initialize table or chart
- ngOnDestroy → Unsubscribe observables
Practical enterprise use cases of hooks
- ngOnInit: Load users or products table from API.
- ngOnChanges: Update chart when parent sends new filter.
- ngAfterViewInit: Access Material Table paginator or sort after view initialized.
- ngDoCheck: Detect array mutations in complex state objects.
- ngOnDestroy: Clean up Subscription and timers to avoid memory leaks.
How do you manage subscriptions with hooks?
Answer:
Use ngOnDestroy with Subject + takeUntil:
private destroy$ = new Subject<void>();
ngOnInit() {
this.api.getData()
.pipe(takeUntil(this.destroy$))
.subscribe();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
✅ Enterprise pattern to prevent memory leaks.
Why use lifecycle hooks over constructor?
Answer:
- Constructor: Only for dependency injection; inputs not ready.
- Hooks: Allow safe access to inputs, views, content, and subscriptions.
- In enterprise apps, hooks ensure predictable component behavior and performance.
Can hooks be used with Observables and AsyncPipe?
Answer:
- ngOnInit → Subscribe to API or store observable.
- ngOnDestroy → Unsubscribe manually if not using async pipe.
- Async pipe auto-unsubscribes, so no manual cleanup is needed.
users$ = this.api.getUsers(); // directly use in template with async pipe
⭐ Interview Tip
Always mention:
- Cleanup in ngOnDestroy
- Difference between constructor and ngOnInit
- Reacting to @Input changes with ngOnChanges
- Accessing child elements with ngAfterViewInit
Interviewers love seeing enterprise-safe practices.
Comments
Post a Comment