Q1. What
is Angular?
Angular
is a TypeScript-based, open-source front-end framework maintained by Google for
building single-page applications (SPAs). It provides a complete solution
including routing, forms, HTTP client, dependency injection, and testing
utilities out of the box.
Q2. What
is the difference between AngularJS and Angular?
●
AngularJS (v1.x) is based on JavaScript and uses MVC
architecture with $scope and controllers.
●
Angular (v2+) is a complete rewrite using TypeScript,
component-based architecture, better performance via the Ivy renderer, mobile
support, and improved dependency injection.
Q3. What
are the key building blocks of an Angular application?
●
Modules (NgModules) — group related code together
●
Components — control views (UI logic)
●
Templates — HTML with Angular syntax
●
Metadata (Decorators) — @Component, @NgModule,
@Injectable, etc.
●
Services — reusable business logic
●
Dependency Injection — supplies dependencies to classes
●
Directives — modify DOM behavior/appearance
●
Pipes — transform data in templates
●
Routing — navigation between views
Q4. What
is a Component in Angular?
A
component controls a section of the UI (a view). It's a TypeScript class
decorated with @Component, which defines a selector, template (HTML), and
styles.
@Component({
selector: 'app-hello',
template: `<h1>Hello, {{name}}</h1>`,
styleUrls: ['./hello.component.css']
})
export class HelloComponent {
name = 'Angular';
}
Q5. What
is a Module (NgModule)?
An
NgModule is a container for a cohesive block of code — components, directives,
pipes, and services. Every Angular app has at least one root module,
conventionally called AppModule, bootstrapped via
platformBrowserDynamic().bootstrapModule(AppModule). Note: since Angular 14+,
standalone components let you skip NgModules entirely by setting standalone:
true and importing dependencies directly in the component.
Q6. What
is the purpose of main.ts?
It's
the entry point of the application. It bootstraps the root module (or root
standalone component in newer Angular versions), which then loads the root
component and the rest of the app.
2. Data Binding & Directives
Q7. What
are the types of data binding in Angular?
●
Interpolation (one-way, component → view): {{ value }}
●
Property binding (one-way, component → view):
[property]="value"
●
Event binding (one-way, view → component):
(event)="handler()"
●
Two-way binding: [(ngModel)]="value"
Q8. What
is the difference between interpolation and property binding?
Interpolation
converts the expression to a string and inserts it into the DOM. Property
binding directly sets a DOM element property with the evaluated expression's
actual value (not just a string), so it's preferred for non-string values like
booleans, objects, or arrays.
Q9. What
are directives, and what types exist?
●
Component directives — directives with a template
(@Component)
●
Structural directives — change DOM layout by
adding/removing elements: *ngIf, *ngFor, *ngSwitch
●
Attribute directives — change appearance/behavior of an
element: ngClass, ngStyle, custom directives
Q10. How
do you create a custom directive?
Example
of a directive that highlights an element on hover:
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective
{
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.el.nativeElement.style.backgroundColor
= 'yellow';
}
@HostListener('mouseleave') onMouseLeave() {
this.el.nativeElement.style.backgroundColor
= null;
}
}
Q11.
What is the difference between *ngIf and [hidden]?
*ngIf
completely adds/removes the element from the DOM. [hidden] keeps the element in
the DOM but toggles CSS display: none. Use *ngIf when the element is expensive
to render or shouldn't exist in the DOM at all (e.g., for security or
performance).
Q12.
What is ngFor trackBy and why use it?
trackBy
tells Angular how to identify unique items in a list, so it can avoid
re-rendering the entire list when the array reference changes but individual
items haven't. This improves performance for large lists.
trackByFn(index: number, item: any) {
return item.id;
}
3. Component Communication
Q13. How
do components communicate with each other?
●
Parent to Child: @Input() decorator
●
Child to Parent: @Output() decorator with EventEmitter
●
Unrelated components: shared service with RxJS
Subject/BehaviorSubject, or state management (NgRx)
●
Via template reference variables (#childRef)
●
ViewChild/ContentChild to access child component
instances directly
Q14.
Example of @Input and @Output:
The
child emits an event; the parent listens for it and passes data down via a
bound input.
// Child
@Component({ selector:
'app-child', template: `<button
(click)="notify()">Send</button>` })
export class ChildComponent {
@Input() data: string;
@Output() notifyParent = new EventEmitter<string>();
notify() {
this.notifyParent.emit('Hello from child');
}
}
<!-- Parent template -->
<app-child
[data]="parentData"
(notifyParent)="onNotify($event)"></app-child>
Q15.
What is ViewChild and ContentChild?
●
@ViewChild() gets a reference to a child
component/directive/DOM element defined in the component's own template.
●
@ContentChild() gets a reference to content projected
into the component via <ng-content> (from the parent's template).
4. Services & Dependency Injection
Q16.
What is Dependency Injection (DI) in Angular?
DI
is a design pattern where a class receives its dependencies from an external
source (Angular's injector) rather than creating them itself. This promotes
loose coupling, testability, and reusability.
Q17.
What is a Service?
A
service is a class with a specific purpose (e.g., fetching data, logging,
business logic) that can be injected into components or other services,
promoting separation of concerns and code reuse.
@Injectable({ providedIn: 'root' })
export class DataService {
getData() { return ['a', 'b', 'c']; }
}
Q18.
What does providedIn: 'root' mean?
It
registers the service as a singleton at the application root injector, making
it tree-shakable (removed from the bundle if unused) and available
application-wide without needing to add it to a module's providers array.
Q19.
What are the different provider scopes?
●
providedIn: 'root' — singleton across the whole app
●
providedIn: 'any' — separate instance per lazy-loaded
module
●
Provided in a specific @NgModule's providers array —
singleton for that module
●
Provided in a component's providers array — new
instance per component instance
Q20.
What is hierarchical dependency injection?
Angular
has a tree of injectors that mirrors the component tree. When a component
requests a dependency, Angular looks up the tree starting from the component's
own injector until it finds a provider. This allows different components to get
different instances of the same service class.
5. Lifecycle Hooks
Q21.
What are Angular lifecycle hooks? List them in order.
●
constructor() — not technically a hook, but runs first
●
ngOnChanges() — called when an @Input property changes
●
ngOnInit() — called once after the first ngOnChanges
●
ngDoCheck() — custom change detection
●
ngAfterContentInit() — after content (ng-content) is
projected
●
ngAfterContentChecked() — after every check of
projected content
●
ngAfterViewInit() — after component's view (and child
views) initialized
●
ngAfterViewChecked() — after every check of the
component's view
●
ngOnDestroy() — cleanup before component is destroyed
Q22.
When would you use ngOnInit vs the constructor?
The
constructor should only be used for simple initialization like injecting
dependencies — it runs before Angular has set up input bindings. ngOnInit is
the right place for initialization logic that depends on @Input values or
requires calling services, since Angular guarantees inputs are set by then.
Q23. Why
is ngOnDestroy important?
It's
used to clean up resources — unsubscribing from Observables, detaching event
listeners, clearing timers — to prevent memory leaks when a component is
removed from the DOM.
6. RxJS & Observables
Q24.
What is an Observable?
An
Observable is a stream of data/events that can be observed over time. It's part
of RxJS and is used extensively in Angular for async operations (HTTP calls,
event handling, forms, routing).
Q25.
What is the difference between Observable and Promise?
|
Observable |
Promise |
|
Can emit multiple values over time |
Resolves once with a single value |
|
Lazy (executes only on subscribe) |
Eager (executes immediately) |
|
Cancellable via unsubscribe() |
Not cancellable |
|
Provides operators (map, filter, etc.) |
No built-in operators |
Q26.
What is the difference between Subject, BehaviorSubject, ReplaySubject, and
AsyncSubject?
●
Subject — no initial value; only emits values to
subscribers after they subscribe.
●
BehaviorSubject — requires an initial value; always
emits the current/last value to new subscribers.
●
ReplaySubject — replays a specified number of previous
values to new subscribers.
●
AsyncSubject — only emits the last value, and only when
the Observable completes.
Q27.
What are common RxJS operators used in Angular?
●
map — transform emitted values
●
filter — filter emitted values
●
switchMap — cancel previous inner observable and switch
to a new one (great for search-as-you-type, avoiding race conditions)
●
mergeMap — run multiple inner observables concurrently
●
concatMap — run inner observables sequentially, in
order
●
debounceTime — wait for a pause in emissions before
emitting
●
distinctUntilChanged — only emit when value changes
●
catchError — handle errors in the stream
●
tap — perform side effects without altering the stream
Q28.
When would you use switchMap vs mergeMap vs concatMap?
●
switchMap: when only the latest request matters (e.g.,
typeahead search) — cancels previous in-flight requests.
●
mergeMap: when all requests should run in parallel and
order doesn't matter.
●
concatMap: when requests must run one after another in
order (e.g., sequential form submissions).
Q29.
What is the async pipe and why use it?
The
async pipe subscribes to an Observable/Promise directly in the template and
automatically unsubscribes when the component is destroyed, preventing memory
leaks and reducing boilerplate.
<div *ngIf="data$ | async as
data">{{ data }}</div>
7. Change Detection
Q30.
What is Change Detection in Angular?
Change
detection is the mechanism by which Angular checks whether the state of the
application has changed and updates the DOM accordingly. By default, Angular
runs change detection on every component whenever an event occurs (click, HTTP
response, timer, etc.) using Zone.js to detect async operations.
Q31.
What is the difference between ChangeDetectionStrategy.Default and OnPush?
●
Default — Angular checks the component on every change
detection cycle, regardless of whether its inputs changed.
●
OnPush — Angular only checks the component when its
@Input reference changes, an event originates from the component/its children,
or an Observable bound via the async pipe emits. This significantly improves
performance in large applications.
Q32.
What is Zone.js and what role does it play?
Zone.js
patches async browser APIs (setTimeout, promises, DOM events, XHR) to notify
Angular when async operations complete, triggering change detection
automatically. Angular is moving toward zoneless change detection
(signals-based) in recent versions to reduce overhead.
Q33.
What are Angular Signals?
Signals
(introduced in Angular 16+, stabilized in 17+) are a reactive primitive that
holds a value and notifies consumers when it changes. Unlike Zone.js-based
change detection, signals allow Angular to track dependencies precisely and
update only the parts of the DOM that depend on the changed signal — enabling
fine-grained, more performant reactivity without Zone.js.
count = signal(0);
increment() {
this.count.update(v => v + 1); }
doubled = computed(() =>
this.count() * 2);
8. Routing
Q34. How
does routing work in Angular?
The
RouterModule maps URL paths to components. Routes are defined in an array of
Routes, and <router-outlet> in the template acts as a placeholder where
the matched component is rendered.
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'user/:id', component: UserComponent },
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
Q35.
What are Route Guards? List the types.
●
CanActivate — decides if a route can be activated
●
CanActivateChild — decides if child routes can be
activated
●
CanDeactivate — decides if a user can leave a route
(e.g., unsaved changes warning)
●
CanMatch (replaces CanLoad) — decides if a route can
even be matched/loaded
●
Resolve — pre-fetches data before activating a route
Q36.
What is lazy loading, and why use it?
Lazy
loading loads feature modules only when their route is visited, rather than at
app startup. This reduces the initial bundle size and improves load time.
{ path: 'admin', loadChildren: () =>
import('./admin/admin.module').then(m => m.AdminModule) }
Q37.
What is the difference between routerLink and [routerLink]?
routerLink="path"
is used for static string paths. [routerLink]="expression" (property
binding) is used when the path is dynamic — e.g., bound to a component property
or array like ['/user', userId].
9. Forms
Q38.
What are the two approaches to handling forms in Angular?
●
Template-driven forms — logic is mostly in the HTML
template using directives like ngModel; simpler, suited for basic forms.
●
Reactive forms — form model is defined explicitly in
the component class using FormGroup, FormControl, and FormBuilder; more
scalable, testable, and suited for complex/dynamic forms.
Q39.
Example of a Reactive Form:
Define
the form model in the component, then bind it in the template with formGroup /
formControlName.
this.form = this.fb.group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
<form
[formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="name">
<input formControlName="email">
</form>
Q40.
What is a custom validator, and how do you create one?
A
custom validator is a function that returns null if valid, or a validation
error object if invalid.
function forbiddenNameValidator(name:
string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
return control.value === name ? {
forbiddenName: { value: control.value } } : null;
};
}
Q41.
What is the difference between FormControl, FormGroup, and FormArray?
●
FormControl — tracks the value/validity of a single
form field.
●
FormGroup — tracks a group of FormControls as one
object.
●
FormArray — tracks an array of FormControls/FormGroups,
useful for dynamic lists of fields.
10. HTTP & Interceptors
Q42. How
do you make HTTP requests in Angular?
Via
HttpClient (from HttpClientModule or provideHttpClient()), which returns
Observables.
constructor(private http: HttpClient) {}
getUsers():
Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
Q43.
What is an HTTP Interceptor?
An
interceptor sits between the app and the backend, intercepting outgoing
requests and incoming responses. Common uses: adding auth headers/tokens,
logging, error handling, showing a loading spinner.
@Injectable()
export class AuthInterceptor
implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const cloned = req.clone({ setHeaders: {
Authorization: `Bearer ${token}` } });
return next.handle(cloned);
}
}
Q44. How
do you handle errors from HTTP calls?
Using
the catchError RxJS operator combined with throwError:
this.http.get('/api/data').pipe(
catchError(err => {
console.error(err);
return throwError(() => new
Error('Something went wrong'));
})
);
11. Pipes
Q45.
What is a Pipe? Give examples of built-in pipes.
A
pipe transforms displayed data in a template. Built-in examples: DatePipe,
CurrencyPipe, UpperCasePipe, LowerCasePipe, DecimalPipe, JsonPipe, PercentPipe,
AsyncPipe.
{{ birthday | date:'shortDate' }}
{{ price | currency:'USD' }}
Q46.
What is the difference between a pure and impure pipe?
●
Pure pipe (default) — only re-executes when Angular
detects a pure change to the input value (a new reference for objects/arrays,
or a changed primitive). More performant.
●
Impure pipe — executes on every change detection cycle
regardless of whether the input actually changed. Needed when the pipe depends
on mutable data (e.g., filtering an array in place), but should be used
cautiously due to performance cost.
Q47. How
do you create a custom pipe?
@Pipe({ name: 'truncate' })
export class TruncatePipe
implements PipeTransform {
transform(value: string, limit = 20): string {
return value.length > limit ?
value.substring(0, limit) + '...' : value;
}
}
12. Testing
Q48.
What testing tools does Angular use by default?
Jasmine
as the testing framework and Karma as the test runner (though many teams now
use Jest). TestBed is Angular's core testing utility for configuring and
creating components in a test environment.
Q49.
What is TestBed?
TestBed
creates a dynamically constructed Angular testing module that emulates an
@NgModule for use in unit tests, allowing you to configure providers,
declarations, and imports for the component under test.
Q50.
What's the difference between a unit test and an end-to-end (e2e) test in
Angular?
Unit
tests verify individual components/services in isolation (often with mocked
dependencies) using Jasmine/Jest + TestBed. E2E tests verify the whole
application flow as a user would experience it in a real browser, typically
using tools like Cypress or Playwright (Protractor was the historical default
but is deprecated).
13. Performance & Optimization
Q51.
What techniques improve Angular app performance?
●
Use OnPush change detection strategy
●
Lazy load feature modules
●
Use trackBy with *ngFor
●
Avoid function calls in templates (they run on every CD
cycle) — use pipes or computed properties instead
●
Unsubscribe from Observables / use the async pipe
●
Use pure pipes over impure ones
●
Enable production builds (AOT compilation,
minification, tree-shaking)
●
Use virtual scrolling (cdk-virtual-scroll) for long
lists
●
Preload strategies for lazy-loaded modules
●
Use signals for fine-grained reactivity (Angular 17+)
Q52.
What is AOT (Ahead-of-Time) compilation vs JIT (Just-in-Time)?
●
AOT compiles templates and TypeScript into efficient JS
during the build process, before the browser downloads/runs the code. Results
in faster rendering, smaller bundles, and earlier error detection. This is the
default for production builds.
●
JIT compiles the app in the browser at runtime. Used
mainly for local development for faster rebuilds.
Q53.
What is tree-shaking?
A
build optimization that removes unused code from the final bundle, reducing
bundle size. Angular's providedIn: 'root' services and ES modules support this.
14. Advanced / Architecture
Q54.
What is content projection (ng-content)?
Content
projection lets a parent component insert (project) content into a child
component's template at a designated spot, marked using <ng-content>.
Useful for building reusable wrapper components (e.g., cards, modals).
<!-- child template -->
<div
class="card"><ng-content></ng-content></div>
<!-- parent usage -->
<app-card><p>This
content gets projected</p></app-card>
Q55.
What is a standalone component?
Introduced
in Angular 14 and made the default in Angular 17+, standalone
components/directives/pipes don't need to be declared in an NgModule. They
import their own dependencies directly, simplifying the mental model and
reducing boilerplate.
@Component({
selector: 'app-hello',
standalone: true,
imports: [CommonModule],
template: `<h1>Hello</h1>`
})
export class HelloComponent {}
Q56.
What is NgRx, and when would you use it?
NgRx
is a state management library for Angular based on Redux principles (single
store, unidirectional data flow, actions, reducers, effects, selectors). It's
useful for large applications with complex shared state, where prop drilling or
scattered services become hard to manage and debug.
Q57.
What are the core building blocks of NgRx?
●
Store — single source of truth (state container)
●
Actions — describe unique events
●
Reducers — pure functions that compute new state from
actions
●
Selectors — pure functions to query slices of state
●
Effects — handle side effects (e.g., API calls)
triggered by actions
Q58.
Root vs module-level providers for singletons in lazy-loaded modules?
A
root-provided service is shared as a true app-wide singleton. If instead the
service is listed in a lazy-loaded module's providers array, Angular creates a
separate instance scoped to that lazy module's injector — a common source of
bugs when developers expect a single shared instance.
Q59.
What is Angular Universal / SSR?
Angular
Universal enables Server-Side Rendering (SSR) — rendering the app to static
HTML on the server before sending it to the browser. This improves perceived
load time, SEO (since crawlers see full content), and performance on
low-powered devices. Angular now has built-in SSR support (ng add @angular/ssr)
with hydration.
Q60.
What is Hydration in Angular?
Hydration
is the process where, after SSR delivers static HTML, Angular
"reuses" the existing DOM on the client instead of destroying and
re-rendering it from scratch, attaching event listeners and making the page
interactive — improving performance and avoiding UI flicker.
15. Common Coding / Scenario Questions
Q61. How
would you share data between sibling components?
Use
a shared service with an Observable (Subject/BehaviorSubject) that both
siblings inject. One sibling emits a new value, the other subscribes to receive
updates.
Q62. How
do you prevent memory leaks from subscriptions?
●
Use the async pipe where possible (auto-unsubscribes)
●
Use takeUntil with a Subject that emits in ngOnDestroy
●
Use take(1) for one-time values
●
Manually call .unsubscribe() in ngOnDestroy if you
stored the Subscription
private destroy$ = new
Subject<void>();
ngOnInit() {
this.service.getData().pipe(takeUntil(this.destroy$)).subscribe(...);
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
Q63. How
would you implement debounced search (typeahead)?
this.searchControl.valueChanges.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap(term => this.searchService.search(term))
).subscribe(results =>
this.results = results);
Q64.
What's the difference between Renderer2 and directly manipulating the DOM via
ElementRef?
Renderer2
provides a platform-agnostic API to manipulate the DOM, which is important for
server-side rendering, web workers, and other environments where direct DOM
access via nativeElement isn't safe or available. Direct DOM manipulation
bypasses Angular's abstraction and can break in non-browser environments.
Q65.
What is the difference between @Input() and @Input({ required: true })?
Available
since Angular 16, @Input({ required: true }) enforces at compile-time that the
parent component must supply this input — omitting it produces a build error,
catching bugs earlier than the runtime undefined you'd otherwise get.
Quick-Fire Round (Rapid Recall)
|
Question |
Short Answer |
|
What compiler does Angular use? |
Ivy (default since Angular 9) |
|
Default change detection strategy? |
Default (checks every component every cycle) |
|
CLI command to create a new project? |
ng new project-name |
|
CLI command to generate a component? |
ng generate component name |
|
How to run unit tests? |
ng test |
|
How to build for production? |
ng build --configuration production |
|
What decorator marks a class as injectable? |
@Injectable() |
|
What decorator defines a module? |
@NgModule() |
|
What's the root component usually called? |
AppComponent |
|
What connects a route to a component? |
RouterModule + <router-outlet> |
No comments:
Post a Comment