Signals, RxJS, NgRx, Ivy, micro-frontends, and change detection: ace the questions senior Angular roles actually ask.
Change Detection
Change Detection is the mechanism Angular uses to update the DOM when the application state changes.
Because with Default Change Detection, Angular runs change detection from the root component down the entire tree, regardless of whether a component's @Input()s changed or not.
So even if the @Input() values passed to the child remain the same (or don’t exist at all), the child will still go through change detection, and Angular will re-evaluate its template expressions to see if anything needs updating.
It doesn’t care why something may have changed. Angular just assumes something might have changed: so it runs CD on everything.
Angular executes an event (e.g., click, setTimeout).
Zone.js detects it.
Angular runs Change Detection starting from the root component and traverses the component tree.
It compares the current and previous values of bindings and updates the DOM if needed.
NgZone is Angular's service that provides a controlled execution context for running code inside or outside Angular's zone.
Purpose: Executes the given function inside the Angular zone, ensuring that Angular's change detection is triggered after the function's execution.
Use Case: When you've executed some code outside Angular's zone (e.g., for performance reasons) and need to re-enter the Angular zone to ensure the UI updates correctly.
this.ngZone.run(() => {
// Code that needs to run inside Angular's zone
});
this.ngZone.runOutsideAngular(() => {
// Code that runs outside Angular's zone
});
this.ngZone.runOutsideAngular(() => {
// Perform some background task
this.ngZone.run(() => {
// Update UI components here
});
});
Hierarchical Dependency Injection
Angular has a built-in DI framework that manages how services or objects are instantiated and how they get injected into components, directives, pipes, or other services. This is done using metadata like the @Injectable() decorator and constructor injection.
If we don't add the service in any component provider array we have single instance of that service across all components,
so If I am storing some data from component that data i can read in another component
now for NgContanierTempComponent, we have separate instance of ProductService service so data store from ChnageDetectionComponent component won't be
present in service object as we have different objcet available for this component
if we have another child component rendered in this component it will share same instance of service we have over here not global one
To create a mock instance of a service, you typically want to simulate a service's behavior without actually calling its real implementation: especially useful in unit testing.
We create a mock class with matching method signatures that returns test doubles (e.g. of(['mock', 'data'])) without invoking real backend endpoints.
class MockMyService {
getData() {
return of(['mock', 'data']);
}
}
providedIn: 'root' (Default)
Scope: Application-wide singleton.
A single instance is shared across the entire application.
No need to add the service to any module's providers array
Supports tree-shaking; unused services are excluded from the final bundle.
providedIn: 'any'
Each lazy-loaded module receives its own instance; eagerly loaded modules share a singleton.
Eagerly loaded modules share a single instance.
Each lazy-loaded module gets a new instance.
Useful when you want to isolate service instances between lazy-loaded modules to prevent shared state.
providedIn: 'platform'
Singleton shared across all Angular applications on the same page.
he service is provided in the platform injector, making it available to multiple Angular apps running simultaneously
Beneficial in micro-frontend architectures or when using Angular Elements, where multiple Angular applications coexist.
providedIn: SomeModule
Specific to the module where it's provided.
The service is available only within the specified module
When you want to restrict a service's availability to a particular feature module.
Scope: Application-wide singleton.
A single instance is shared across the entire application.
No need to add the service to any module's providers array
Supports tree-shaking; unused services are excluded from the final bundle.
Each lazy-loaded module receives its own instance; eagerly loaded modules share a singleton.
Eagerly loaded modules share a single instance.
Each lazy-loaded module gets a new instance.
Useful when you want to isolate service instances between lazy-loaded modules to prevent shared state.
Singleton shared across all Angular applications on the same page.
he service is provided in the platform injector, making it available to multiple Angular apps running simultaneously
Beneficial in micro-frontend architectures or when using Angular Elements, where multiple Angular applications coexist.
Specific to the module where it's provided.
The service is available only within the specified module
When you want to restrict a service's availability to a particular feature module.
@Injectable({ providedIn: 'root' })
export class GlobalService {}
@Injectable({ providedIn: 'any' })
export class ModuleScopedService {}
@Injectable({ providedIn: 'platform' })
export class SharedPlatformService {}
service Decorators
@Self(): Only look for the dependency in the current injector.
@SkipSelf(): Look for the dependency in parent injectors.
@Optional(): If the dependency isn't found, inject null instead of throwing an error.
@Host(): Look for the dependency in the current component's injector or its host.
@Self(): Only look for the dependency in the current injector.
@SkipSelf(): Look for the dependency in parent injectors.
@Optional(): If the dependency isn't found, inject null instead of throwing an error.
@Host(): Look for the dependency in the current component's injector or its host.
Angular Ivy
Just like how we use console in JavaScript same way we can debug angular app as well
Each component is compiled in isolation. No need for the full app context.
Unused parts of Angular and components are dropped during build.
Ivy is the new rendering engine introduced in Angular 9
Think of Ivy as the engine that powers how Angular compiles and renders your components
Ivy exposes internal APIs like ng.getComponent(), ng.getInjector(), and ng.getHostElement() in the browser console.
Enables faster builds and rebuilds
Makes library development modular
Ivy's compiler generates code that's more tree-shakable.
Smaller bundles = better performance.
Templates are compiled to highly optimized JS instructions (ɵɵ instructions).
This removes the need for metadata JSON files (.metadata.json) and factory files (.ngfactory.ts), making libraries easier to publish and consume.
Go to Shell Project and run below
Go to Remote Project and run below
open remote/webpack.config.js
shell/webpack.config.js
app.config of shell
run remote Project
run shell Project
ng new shell --routing --style=scss ng new remote --routing --style=scss
ng add @angular-architects/module-federation --project shell --type host Enter
port 4200 Select Module Federation with webpack (classic) Select Y
ng add @angular-architects/module-federation --project remote --type remote
Enter port 4201 Select Module Federation with webpack (classic) Select Y
<ng-container> is a special grouping element that Angular does not render into the DOM tree. It acts as an invisible host for structural directives without adding unnecessary wrapper elements (like <div> or <span>).
Prevents DOM bloat by grouping elements without rendering extra tags.
Allows applying structural directives (*ngIf, *ngFor) without breaking HTML layout (e.g. <tr>/<td> in tables).
Acts as a target container for dynamic view insertion using ViewContainerRef.
<ng-container *ngIf="isLoggedIn">
<h2>Welcome Back!</h2>
<p>Here is your personalized dashboard.</p>
</ng-container>
ngTemplateOutlet
ngTemplateOutlet dynamically inserts a template defined by <ng-template> into the DOM. It also allows passing custom context data into the template for reusable UI components.
Renders an <ng-template> dynamically inside an <ng-container>.
Supports passing custom context objects via [ngTemplateOutletContext].
Ideal for customizable cards, reusable table columns, and dynamic widgets.
Using <ng-template> in conjunction with *ngIf; else allows clean view swapping for loading states, error fallbacks, or conditional views without nested checks.
Provides a declarative fallback (else) block for *ngIf.
Keeps template logic clean without writing duplicate opposite if conditions.
Actions define what can happen in the application. They are simple objects describing an event. actions don't contain any logic; they just describe what happens
means when you create your store what Operation you can provide with that store that you define over here. Like for Counter Increment and Decrement
counter.actions.ts
When the user clicks the "Increment" button, we dispatch the increment action.
A reducer is a pure function that takes the current state and an action and returns the new state.
Reducers are pure functions, meaning they don't modify the originnal state but return a new state.
counter.actions.ts
createReducer() defines how the state should change based on actions:
import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from './counter.actions';
export const initialState = 0;
export const counterReducer = createReducer(
initialState,
on(increment, (state) => state + 1),
on(decrement, (state) => state - 1),
on(reset, () => 0),
);
Step 3: Create State Interface
app.state.ts
export interface AppState {
count: number;
}
Step 4: Register Reducer in Store in app.module.ts
The Store is like a global state container that holds all application state
app.module.ts
app.config.ts
StoreModule.forRoot({ count: counterReducer }) => Registers the counterReducer in the global store. and count becomes the key in the state.
The Store is like a global state container that holds all application state
store.select('count') => this is how we read data from store by select method and prviding state name
The reason we use this.store.pipe(select('count')) instead of this.store.select('count') directly is due to how RxJS and NgRx handle state selection.
select() is an RxJS operator and In NgRx, select() is not a method on Store , Since it is an operator, it must be used inside
dispatch action => this actually by using action we are trigging our reducer
[ User Clicks Button ] ↓ [ Component Dispatches Action ] ↓ [ Action Sent to
Store ] ↓ [ Reducer Updates State ] ↓ [ Store Emits New State ] ↓ [ Component
Receives Updated State ] ↓ [ UI Updates Automatically ]
How to Optimize Angular Applications
Use Lazy Loading (Route-Level Code Splitting)
Split app into modules (AdminModule, UserModule, etc.)
Use Angular Router’s loadChildren to lazy load those modules
Enable Change Detection Optimization
Only re-renders component if @Input() changes
Improves performance, especially in large UIs
Use TrackBy in *ngFor
With trackBy, only changed items are updated
Avoid Memory Leaks (Especially in RxJS)
Always unsubscribe from subscriptions using:
takeUntil(), AsyncPipe
Subscription management in ngOnDestroy
Use Pure Pipes for Expensive Transformations
Pure pipes are only re-evaluated when input changes.
Use Web Workers for Heavy Computation
Offload CPU-heavy tasks (e.g., data parsing, image processing) to Web Workers.
Lazy Load Images and Components
Use loading="lazy" on
Split app into modules (AdminModule, UserModule, etc.)
Use Angular Router’s loadChildren to lazy load those modules
Only re-renders component if @Input() changes
Improves performance, especially in large UIs
With trackBy, only changed items are updated
Always unsubscribe from subscriptions using:
takeUntil(), AsyncPipe
Subscription management in ngOnDestroy
Pure pipes are only re-evaluated when input changes.
move Offload CPU-heavy tasks (e.g., data parsing, image processing) to Web Workers.
Use loading="lazy" on
How do you secure an Angular app?
Route Guards
We should use canActivate, canLoad, and canActivateChild to restrict unauthorized access, based on roles or auth status.
Interceptors
use HttpInterceptors to inject tokens into headers securely, and also handle unauthorized responses globally.
CSRF Protection
For cookie-based auth, I work with backend teams to enable CSRF protection using X-XSRF-TOKEN, which Angular supports out of the box.
Avoid Exposing Secrets
make sure not to hardcode API keys or secrets in Angular, since all front-end code is publicly visible.
Token Security
we should prefer storing JWTs in HttpOnly cookies to avoid XSS risks.
If localStorage or sessionStorage is used, we should ensure input sanitization and logout on suspicious activity.
HttpOnly cookies: They are stored by the browser itself, and not accessible via document.cookie or JavaScript. You only see them in the "Application → Cookies" tab in dev tools.
this.http.get('/api/user-profile', { withCredentials: true }).subscribe(...)
We should use canActivate, canLoad, and canActivateChild to restrict unauthorized access, based on roles or auth status.
use HttpInterceptors to inject tokens into headers securely, and also handle unauthorized responses globally.
For cookie-based auth, I work with backend teams to enable CSRF protection using X-XSRF-TOKEN, which Angular supports out of the box.
make sure not to hardcode API keys or secrets in Angular, since all front-end code is publicly visible.
we should prefer storing JWTs in HttpOnly cookies to avoid XSS risks.
If localStorage or sessionStorage is used, we should ensure input sanitization and logout on suspicious activity.
HttpOnly cookies: They are stored by the browser itself, and not accessible via document.cookie or JavaScript. You only see them in the "Application → Cookies" tab in dev tools.
Split large modules into lazy-loaded chunks using routes:
Angular and Webpack remove unused code ( but only if it's structured well)
Helps reduce boilerplate, improves tree-shakability and bundling.
Avoid large barrel exports
Don’t bundle everything in a single shared module
Mark classes with providedIn: 'root' for optimal tree-shaking
When you write Angular code using TypeScript, SCSS, etc., it's not what the browser actually runs. The browser
gets compiled JavaScript, CSS, and HTML.
But when you're debugging, you want to see your original TypeScript code, not the ugly minified JS.
That’s where source maps come in, they’re like a translator between your original source code and the compiled
output.
Faster rendering
Smaller bundles
Detects template errors at build time
The Angular CLI now supports ESBuild: much faster than Webpack for transpiling.
create separate bundles for modern and legacy browsers.
Angular CLI handles this automatically
es2015 for modern browsers
es5 fallback for older ones
Use ChangeDetectionStrategy.OnPush to avoid unnecessary checks:
Memoization is an optimization technique where you cache the result of expensive function calls and return the cached result when the same inputs occur again.
Webpack is a module bundler. Think of it as a super-efficient packer: it takes all your project files (JavaScript, CSS, images, HTML, etc.), analyzes their dependencies, and bundles them into optimized files that can be shipped to the browser.
Webpack is the engine behind Angular CLI's build system. It bundles your code, optimizes it, splits it for lazy loading, processes your assets, and prepares everything for efficient browser delivery.
Webpack takes your Angular components, services, pipes, directives, and other modules and builds a dependency graph.
Then it bundles these modules into efficient JavaScript files (like main.js, polyfills.js, etc.).
Webpack loads and processes your styles (CSS/SCSS), HTML templates, and images using loaders
Removes unused code (dead code elimination).
This significantly reduces bundle size in production builds
Webpack enables lazy loading and dynamic imports to split your app into smaller chunks.
This means only the necessary code is loaded initially, improving performance.
Angular uses Webpack to replace environment files (environment.ts vs environment.prod.ts) during build time.
Removes white spaces, comments, shortens variable names, etc.
Also optimizes images, CSS, and other static files
Generates .map files so that even after code minification, you can debug using original source code in the browser.
What is Babel?
Babel is a JavaScript compiler. Think of it like a translator that:
Converts modern JavaScript (ES6+ or TypeScript) into older versions (like ES5) that all browsers can understand.
Allows use of cutting-edge JS features without worrying about browser support.
Transpile ES6+ code to ES5
Transpile JSX (React syntax) to plain JS
Polyfill new APIs like Promise, Array.from, etc.
XSS (Cross-Site Scripting)
XSS is when an attacker injects malicious JavaScript into your application: often via input fields, query params, or URLs.
p {{ userInput }} p
userInput ="<script>alert('x')script>"
Angular compiles your HTML templates + TypeScript code in the browser, as the app loads.
Angular pre-compiles your templates and code before shipping to the browser.
You write TS and templates.
Angular sends them raw-ish to the browser.
Angular compiler runs in the browser and compiles templates into JS on the fly.
Angular CLI compiles HTML & TS into pure JavaScript during ng build.
Removes Angular compiler from final bundle.
Faster rendering in the browser, Smaller bundle size,Early error detection
Accessibility in angular
We ensure all interactive elements are keyboard-accessible using tabindex, role, and HostListener for key events."
use LiveAnnouncer and FocusTrap from Angular CDK to make dynamic interactions accessible.
avoid using divs or spans for interactivity unless I add the necessary ARIA roles and keyboard logic.
Keyboard Navigation: Users should be able to use the app using just a keyboard (Tab, Enter, Space, etc.).
Screen Readers: The UI should be understandable by screen readers (like NVDA, JAWS).
Semantic HTML: Use elements for what they mean (, , , etc.).
Color Contrast: Make sure there's enough contrast between text and background.
Focus Management: Properly manage focus (especially after navigation/dialogs).
ARIA attributes: aria-label, aria-hidden, role, etc., to enhance semantics for assistive tech.
Live announcements with cdk/LiveAnnouncer
switchMap Operator
switchMap projects each source value to an inner Observable. When a new source value arrives, switchMap immediately cancels (unsubscribes from) any pending inner Observable and switches to the new one.
Cancels in-flight inner HTTP requests when a newer event occurs.
Perfect for typeahead/search autocomplete where only the latest keystroke response matters.
Prevents race conditions where a slow previous response overwrites a faster recent response.
Do not use for save/submit operations where every request must complete (use mergeMap or concatMap instead).
Accesses elements, directives, or components within the view DOM of the current component.
When you need to interact with or manipulate child components or elements that are part of the component's own template
we can create instance of Html Element or Component instance
in template
in component.ts
in template
in .ts
Accesses elements, directives, or components within the view DOM of the current component.
When you need to interact with or manipulate child components or elements that are part of the component's own template
we can create instance of Html Element or Component instance
Accesses elements or components that are projected into the component using ng-content directive
When you need to interact with or manipulate content projected from a parent component into the child component
child component Templae
in app-component template
Accesses elements or components that are projected into the component using ng-content directive
When you need to interact with or manipulate content projected from a parent component into the child component
app-my-button span #icon class="fa fa-user" span span Save User span
app-my-button
ViewContainerRef
Represents a container where one or more views can be dynamically added or removed
means instead of usi9ng selector to render component we create instance of component in.ts and inject that into ng-container
Template
.ts code
Represents a container where one or more views can be dynamically added or removed
means instead of usi9ng selector to render component we create instance of component in.ts and inject that into ng-container
A Web Worker runs JavaScript in a background thread, separate from the main UI thread.
So if something is CPU-intensive (like parsing, encrypting, image processing, etc.), you can offload it to a worker and keep the UI fast and responsive.
You're building a finance dashboard (think high-frequency trading platform) in Angular, and you're fetching gigantic JSON datasets every 5 seconds.
Parsing them in the main thread causes frame drops and freezes the UI
You're building an Angular reporting tool where users can download detailed reports (with tables, charts, and summaries) as PDFs.
But generating a PDF (especially with large data and canvas charts) takes 3–5 seconds and blocks the UI: your app freezes.
you can pass a signal to change another signal value based on one signal value change, reactive
signal it's value will depend on value change on signal we pass.
We can't changed computed signal value it will change if dependent value changes
doubleCount signal value will change after 5 sec
linked signals are reactive variables that depend on other signals and update automatically when
their dependencies change: like computed values.
in source you can pass which signal we need to track if source changes then only it will compute
again
total signal state value will change after 8 sec only as in source that value is there
Core concepts and implementation techniques in modern Angular.
What is a component in Angular?
A component is the fundamental building block of an Angular application. It controls a section of
the UI.
It can have multple files as
A TypeScript class (logic)
HTML template (view)
optional CSS style file
A TypeScript class (logic)
HTML template (view)
optional CSS style file
What is Standalone Component ?
Standalone components are a new type of Angular component that does not need to be declared in a NgModule .
These are components that can be used directly in the template of another component without being part of an
NgModule, or imported in an NgModule.
We Define standalone component by adding standalone field as true
From Angular 16 we got standalone components
From 18 By Defyalt all Components are standalone
Standalone components are a new type of Angular component that does not need to be declared in a NgModule .
These are components that can be used directly in the template of another component without being part of an
NgModule, or imported in an NgModule.
We Define standalone component by adding standalone field as true
The @Component decorator tells Angular that the class is a component, in component decorator we
have so many options like
selector: Defines the custom HTML tag used to embed the component.
template: Inline HTML content for the component.
templateUrl: Path to an external HTML file for the component template.
styles: Inline CSS styles applied specifically to this component.
styleUrls: Path(s) to external CSS/SCSS files for styling the component.
providers: Registers services at the component level (local DI).
encapsulation: Controls style encapsulation (Emulated, None, or ShadowDom).
changeDetection: Sets the change detection strategy (Default or OnPush).
imports: (Standalone only) Modules/components this standalone component
depends on.
standalone: (Angular 14+) Declares this component as standalone (not part
of a module).
selector: Defines the custom HTML tag used to embed the component.
template: Inline HTML content for the component.
templateUrl: Path to an external HTML file for the component template.
styles: Inline CSS styles applied specifically to this component.
styleUrls: Path(s) to external CSS/SCSS files for styling the component.
providers: Registers services at the component level (local DI).
encapsulation: Controls style encapsulation (Emulated, None, or ShadowDom).
changeDetection: Sets the change detection strategy (Default or OnPush).
imports: (Standalone only) Modules/components this standalone component
depends on.
standalone: (Angular 14+) Declares this component as standalone (not part
of a module).
Data Binding in Component
One Way Data Binding
Two Way Data Binding
From .ts to .html
From .html to .ts
Using ngModel
Property Binding
Interpolation
Event Binding
Property Binding
Interpolation
Event Binding
@Input() and @ Output() decorators and how are they used?
@ Input(): Pass data from parent to child
@Output(): Send event/data from child to parent
@ Input(): Pass data from parent to child
@Output(): Send event/data from child to parent
Various ways of component communication
To pass data from one component to another there are following ways based on scenario
using Input and Output.
using viewChild.
using service by storing value into variables.
using Subject & SubjectBehaviour of RXJS.
using routing i.e. navigating from one component to another with query param.
store data in local Storage or session Storage and read data wherever we need.
What is Design Pattern
Design patterns are proven solutions to common software design problems. we often use them to
keep my Angular applications scalable and maintainable.
Singleton pattern is naturally used in Angular services (when provided in root).
Observer pattern is the core of RxJS: I use it to react to real-time data, like user auth
status or notifications.
I use the Strategy pattern when I want interchangeable behaviors: like different login or
payment methods.
Angular’s decorators like @Component and @Injectable are based on the Decorator
pattern, which adds metadata and behavior to classes.
I’ve also used the Factory pattern for dynamic service creation based on app config.
Singleton Pattern
A class has only one instance throughout the app
Angular services by default follow Singleton pattern when provided in root. This ensures there’s only one instance shared across the app unless scoped differently.
Factory Pattern
Create objects without exposing the creation logic to the client.
Sometimes I use factories to create service instances dynamically: for example, selecting a payment gateway like RazorPay or Stripe based on config at runtime.
{ provide: PaymentService, useFactory: (configService: ConfigService) => {
return configService.useStripe ? new StripeService() : new RazorPayService(); },
deps: [ConfigService] }
Observer Pattern
Allows subscribing to state changes.
Angular uses RxJS which is built around the Observer pattern. Components subscribe to observables from services to react to data changes
Strategy Pattern
When I need different behavior based on conditions, I define strategies and inject the right one. Like choosing between different login mechanisms: Google, Facebook, Email
LoginStrategy interface → EmailLogin, GoogleLogin,
Decorator Pattern
Adds additional behavior to an object without altering its structure.
Angular decorators like @Component, @Injectable, and @Directive are actual examples of the decorator pattern. They attach metadata and behavior to classes.
What are directives
Directives add behaviour to an existing DOM element or an existing component instance.
Multple directives can be applied to single DOM element. It inform how DOM Element should behave
Like in case of *ngIf it add or remove element
by ngClass or ngStyle it add dynamic class or css to DOM Element
ngModel sync variable with texbox value
Types of Directives
Structural Directive - responsible to add or remove elements from DOM *ngIf
, *ngFor.
Attribute Directive - responsible to add extra behavior to existing element
- ngClass, ngStyle
Component - directive with a template
Custom Directive - you can create custom directive by cli command ng
generate directive directive_name
Structural Directive - responsible to add or remove elements from DOM *ngIf
, *ngFor.
Attribute Directive - responsible to add extra behavior to existing element
- ngClass, ngStyle
Component - directive with a template
Custom Directive - you can create custom directive by cli command ng
generate directive directive_name
What is Structural Directive ?
Structural Directive are responsible to change structure of DOM, means they can add or remove element from DOM or
Create New Elements also.
*ngIf Directive ?
*ngIf => needs Boolean value if true will render element or it will remove. we can pass variable, comparsion or function as well
trackBy option in *ngFor allows you to specify a function that Angular can use to track items by a unique identifier instead of relying on object reference identity. This identifier helps Angular keep track of which items have changed, been added, or been removed when the data changes. It improves performance, especially when dealing with large lists, by avoiding unnecessary re-rendering of DOM elements.
Home Part 1
Check Youtube Video
Angular Lifecycle Hooks
Button
Angular components and directives have a series of lifecycle phases from creation to destruction.
Lifecycle hooks are special methods that allow you to write code onto these phases to execute custom logic.
ngOnChanges
Invoked when any data-bound input property changes.
Reacting to changes in @Input() properties
Invoked when any data-bound input property changes.
The ngDoCheck lifecycle hook in Angular is a powerful tool for implementing custom change detection logic, especially when Angular's default change detection doesn't suffice.
Means Lets say you have a reusable component with input and you are getting object in that Input now in parent component if you change variable value which you're passing as Input you ngOnChanges
in Child component will execute but if you just changed one field value in parent
component you ngOnchange won't execute in that case you can detect changes in ngDoCheck
export class MyButtonComponent implements DoCheck, OnChanges {
@Input() user!: { name: string; age: number };
private differ!: KeyValueDiffer<string, any>;
constructor(private differs: KeyValueDiffers) {}
ngOnChanges(changes: SimpleChanges): void {
debugger;
//this will trigger if in parent
}
ngOnInit() {
this.differ = this.differs.find(this.user).create();
}
ngDoCheck() {
const changes = this.differ.diff(this.user);
if (changes) {
changes.forEachChangedItem((item: any) => {
console.log(
'Property {item.key} changed from {item.previousValue} to {item.currentValue}',
);
});
}
}
}
Called after Angular initializes the component's views and child views.
Accessing ViewChild() or ViewChildren() properties.
or DOM Interactions: Access and manipulate DOM elements only after the view has been initialized
Called after Angular initializes the component's views and child views.
Accessing ViewChild() or ViewChildren() properties.
or DOM Interactions: Access and manipulate DOM elements only after the view has been initialized
Angular 17 introduced a built-in control flow syntax using the @ block syntax (@if, @for, @switch), replacing the traditional structural directives (*ngIf, *ngFor, *ngSwitch). It offers better performance, type narrowing, and cleaner syntax without needing to import CommonModule.
@if / @else if / @else: Direct conditional branching with automatic TypeScript type narrowing in template expressions.
@for: Iterative loops with a mandatory track expression for optimal DOM reconciliation and built-in @empty block for empty arrays.
@let, was introduced to declare variables directly within templates. This
enhances template logic and readability by allowing the creation of aliases for complex
expressions or values that may be used multiple times.
you can pass a signal to change another signal value based on one signal value change, reactive
signal it's value will depend on value change on signal we pass.
We can't changed computed signal value it will change if dependent value changes
doubleCount signal value will change after 5 sec
linked signals are reactive variables that depend on other signals and update automatically when
their dependencies change: like computed values.
in source you can pass which signal we need to track if source changes then only it will compute
again
total signal state value will change after 8 sec only as in source that value is there
zoneless change detection mechanism that eliminates the need for zone.js, leading to
improved performance and better debugging capabilities.
means now you can disable change detection overall project
Angular forms now expose a property called events, which allows you to subscribe to a stream of
events for this form control.
can track changes in value, touch state, pristine status, and the control status.
const nameControl = new FormControl<string | null>('name', Validators.required);
nameControl.events.subscribe((event) => {
// process the individual events
});
resource api
resource() is a new reactive way that helps manage asynchronous data (like HTTP calls, promises,
or observables) in a declarative, signal-based way.
Browsers enforce the Same-Origin Policy, which restricts web pages from making requests to a different domain than the one that served the web page. This policy enhances security but can lead to CORS errors when your frontend application tries to access resources from a different origi
To bypass CORS restrictions, you can set up a proxy server that acts as an intermediary between your frontend application and the external API. Since CORS policies are enforced by browsers and not servers, the proxy server can make requests to the external API and relay the responses back to the frontend.
create a file named proxy.conf.json.
In your angular.json file
polyfills are scripts that add support for features that are not natively available in all browsers. They essentially "fill in the gaps" to ensure your Angular app works consistently across different environments.
Polyfills help bridge this gap by emulating modern features in older browsers.
Array.includes()
Different browsers support different features of JavaScript and web APIs. For example:
Modern browsers support ES6+ features.
Older versions (like Internet Explorer 11) do not.
const isValid = [1, 2, 3].includes(2);
import 'core-js/es/array/includes';
Hot and Cold Observables in RxJS
A cold observable creates a new execution for each subscriber: like an HTTP call. A hot observable shares the same data stream among all subscribers: like fromEvent or a Subject. In Angular, cold observables are common for APIs, but we can convert them to hot ones using shareReplay when caching is needed.
Starts emitting only when someone subscribes.
Each subscriber gets separate data streams.
Each subscriber gets a different random value.
Subscribers share the same source. It emits even if no one is listening yet.
in.ts
in.html
debounceTime => it will wait for particular time the it will execute
distinctUntilChanged=> it will check if old value is same or not - in case of copy paste we can have same value pasted again so it should not trigger api call
switchMap => if existing api call going on & before response came another api call trigger it will cancel previous api call
filter => it's checking if min 3 char is there then only it will trigger api call
debounceTime => it will wait for perticular time the it will execute
distinctUntilChanged=> it will check if old value is same or not - in case of copy paste we can have same value pasted again so it should not trigger api call
switchMap => if existing api call going on & before response came another api call trigger it will cancel previous api call
filter => it's checking if min 3 char is there then only it will trigger api call
Here we get City Array
Here Subscribe block will execute for every element in array, each time we will get single element like for loop
this is like setInterval from javaScript, if will emit data after 1 sec
subscribe will execuite after 1 sec
const stateFilter$ = this.stateFilter.valueChanges; const cityFilter$ =
this.cityFilter.valueChanges;
combineLatest([stateFilter$,cityFilter$]).subscribe((res:any)=>{ this will
execute when both dropdown has value })
stateFilter$.pipe( combineLatestWith(cityFilter$) ).subscribe((result:any)=>{
this will execute when both dropdown has value })
switchMap | mergeMap | concatMap | exhaustMap
🌀 switchMap: The Smart Replacer
It cancels the previous inner observable whenever a new one comes in.
Useful when you only care about the latest emitted value.
✅ Great for: Autocomplete, live search, debounced input
🌊 mergeMap: The Parallel Player
It subscribes to all inner observables concurrently.
Doesn’t cancel anything, so all requests will go through.
✅ Great for: Making multiple API calls in parallel
No control over completion order
🚶♂️concatMap: The Queue Follower
Waits for each inner observable to complete before subscribing to the next.
Preserves order
Great for: Step-by-step processes-Save form => Upload image => Send confirmation
🚫 exhaustMap: The Gatekeeper
Ignores new emissions if there’s an active inner observable.
Good for avoiding duplicate actions: like preventing multiple api calls.
if one api call is in progress - it won't process another api call
It cancels the previous inner observable whenever a new one comes in.
Useful when you only care about the latest emitted value.
✅ Great for: Autocomplete, live search, debounced input
It subscribes to all inner observables concurrently.
Doesn’t cancel anything, so all requests will go through.
✅ Great for: Making multiple API calls in parallel
No control over completion order
Waits for each inner observable to complete before subscribing to the next.
Preserves order
Great for: Step-by-step processes-Save form => Upload image => Send confirmation
Ignores new emissions if there’s an active inner observable.
Good for avoiding duplicate actions: like preventing multiple api calls.
if one api call is in progress - it won't proccess another api call
SOLID is an acronym for 5 design principles that make software designs more understandable, flexible, and maintainable.
S: Single Responsibility Principle (SRP): A class or component should have only one reason to change.
O: Open/Closed Principle (OCP): Software entities should be open for extension, but closed for modification.
L: Liskov Substitution Principle (LSP): Subtypes must be substitutable for their base types without breaking the application.
I: Interface Segregation Principle (ISP): Many client-specific interfaces are better than one general-purpose interface.
D: Dependency Inversion Principle (DIP): Depend upon abstractions (interfaces), not concrete implementations.
S => Single Responsibility Principle (SRP)
A class or component should have only one reason to change.
A component, service, or class should do only one job. In Angular, I make sure my components only
manage the UI, and all data-fetching or logic goes into services. That way, if I need to change
the UI or logic, I don’t touch both places
Component handles view/UI logic only
Services handle business logic or HTTP logic
This separation makes your code testable and reusable.
O => Open/Closed Principle (OCP)
Software entities should be open for extension but closed for modification.
If a class says it implements something, it should behave like it. In Angular, if I replace one
service with another (like EmailService → SMSService), everything should still work, as long as
both follow the same interface.
If I need to support a new login method, I don't rewrite my AuthService. Instead, I plug in a new
strategy or class: so old logic stays safe and unchanged.
In Angular: Use inheritance, interfaces, or strategy pattern to extend without modifying.
We should be able to extend functionality without rewriting old code.
Derived classes must be substitutable for their base class.
Classes/components should only depend on what they actually use. Instead of having one big user
interface with every possible field, I split them based on use-case: like Profile info, Address
info, Cart info: so each module only depends on what it needs.
In Angular: Use interface-based DI: ensure derived services behave like the base
class/interface.
Clients should not be forced to depend on interfaces they don’t use.
High-level parts of the app shouldn’t be tightly tied to low-level details. I inject services
using interfaces or tokens, not direct classes. That way, I can swap APIs or services without
touching the components that use them.”
In Angular: Create focused interfaces, not "God interfaces".
Now different components/services can use only what they need
High-level modules should not depend on low-level modules. Both should depend on abstractions (interfaces or abstract classes). In Angular, DIP is naturally achieved through Hierarchical Dependency Injection.
High-level components/services depend on abstract class tokens rather than concrete service classes.
Allows easily swapping implementations (e.g., MockService for testing, ProductionService for live app).
Configured in providers array using { provide: LoggerService, useClass: ConsoleLoggerService }.
In Angular, I apply SOLID principles daily. For example, I keep components focused on view logic
(SRP), use strategy patterns and interfaces to switch services without modifying existing code
(OCP & DIP), and write lean interfaces specific to the context (ISP). Angular’s DI system makes
it easy to follow these principles and build scalable apps."
interval(1000)
.pipe(
filter((val) => val % 2 === 0), // only even numbers
)
.subscribe((val) => console.log('Even:', val));
this.searchControl.valueChanges
.pipe(filter((text) => text.length >= 3))
.subscribe((value) => {
// Trigger API call here
});
tap operator
but here we are extracting only fddMeasurements but storing whole response in service variable
api full Response
originalData: any;
getTestById() {
return this.http
.get('https://projectapi.gerasim.in/api/SoilTest/GetTestById?id=1')
.pipe(
tap((response) => {
//here we catch original data
this.originalData = response;
}),
//then we modify data and send it back to subscriber
map((result: any) => result.fddMeasurements),
);
}
}
Both Are are Multicasting Observables Means They allow multiple subscribers to listen to the same Observable stream. However, they differ in how they handle emissions, especially initial values and replay behavior.
subject
How to Create Subject
how to use Next and Subscrbe
userName$ = new Subject<string
>; fullName$ = new Subject<void>
=> when No data Emit; lastName : Subject<string>
= new Subject<string
>(); middleName = new Subject<string
>(); If you Try to Initialize middleName = new Subject<string
>("Demo") => Error Expected 0 arguments, but got 1;</string
></string
></string
></string
></void
></string
>
What is Unit Testing in Angular, and why is it important?
Unit testing in Angular is the process of testing individual pieces of code, like components, services, pipes, or directives, in isolation. The main goal is to ensure that each unit of the app works as expected independently.
Detect bugs early before integration
Improve code reliability and confidence in refactoring
Acts as documentation for how each unit should behave
Jasmine – for writing the test specs
Karma – as the test runner (executes the tests in a browser environment)
What is TestBed in Angular?
TestBed is the primary Angular testing utility that allows you to create an Angular testing module, like a mini Angular app, just for the test environment.
Declare components, pipes, and directives you want to test.
In Jasmine, beforeEach() is a special function that runs before each test case (it()) in a describe block. Think of it as a setup step to prepare your test environment before each individual test runs.
Avoid repeating code (like component setup or service creation).
Ensure each test starts with a fresh, clean state
What is describe in Jasmine
describe() is a test suite: it’s a way to group related test cases (it() blocks) together under a common description.
It helps organize your tests into logical blocks, so when you run them in Karma, you can easily see which group of tests passed or failed.
xdescribe() : Skip the whole suite
xit() – Skip just one test
fdescribe() – Focus only this suite
View Encapsulation Modes
View Encapsulation determines how styles defined in a component are scoped. Angular provides three encapsulation modes: Emulated (default), ShadowDom, and None.
ViewEncapsulation.Emulated (Default): Simulates Shadow DOM by adding unique attributes (_ngcontent-c12) to HTML elements and scoping CSS selectors.
ViewEncapsulation.ShadowDom: Uses the browser's native Shadow DOM API to achieve true isolation.
ViewEncapsulation.None: Styles are injected into the global document <head> without scoping, affecting the whole page.
Shadow DOM is a web standard that enables encapsulation of a component's internal structure and styling, ensuring that its internal DOM and CSS are isolated from the rest of the document.
This means styles defined within a Shadow DOM do not affect the main document, and vice versa.
In Emulated mode, Angular simulates the behavior of the Shadow DOM by modifying the component's styles and template during compilation. It does this by:
Adding Unique Attributes to Elements Angular appends unique attributes to the component's HTML elements. These attributes are typically in the form of _ngcontent-xyz, where xyz is a unique identifier.
Modifying CSS Selectors:Angular updates the component's CSS selectors to target these unique attributes, ensuring that the styles apply only to the elements within the component.
Create a reusable component, lets say Button component have a class added title on button
now in parent component create a class title with some color
in emulated case - title class wont get applied to button component
in none case title class from parent component n will get applied to child component as well
it means it will limit css within that component only
encapsulation: ViewEncapsulation.None
No encapsulation; styles are applied globally and can affect other components.
To Test This
Create a reusable component, lets say Button component have a class added title on button
now in parent component create a class title with some color
in none case title class from parent component n will get applied to child component as well
it means it will limit css within that component only
No encapsulation; styles are applied globally and can affect other components.
Create a reusable component, lets say Button component have a class added title on button
now in parent component create a class title with some color
in none case title class from parent component n will get applied to child component as well
it means it will limit css within that component only
encapsulation: ViewEncapsulation.ShadowDom
Utilizes the browser's native Shadow DOM to encapsulate styles, providing true style isolation
it won;t use any bootstrap or any global css as well, only css which are present in component
To Test This
Create a reusable component, lets say Button component have a class added title on button
now in parent component create a class title with some color
in none case title class from parent component n will get applied to child component as well
it means it will limit css within that component only
Utilizes the browser's native Shadow DOM to encapsulate styles, providing true style isolation
it won;t use any bootstrap or any global css as well, only css which are present in component
Create a reusable component, lets say Button component have a class added title on button
now in parent component create a class title with some color
in none case title class from parent component n will get applied to child component as well
it means it will limit css within that component only
Real-Time Scenario
EmulatedComponent: Uses ViewEncapsulation.Emulated to ensure its styles don't leak out.
ShadowDomComponent: Uses ViewEncapsulation.ShadowDom for true style isolation.
NoneComponent: Uses ViewEncapsulation.None, allowing its styles to affect other components.
EmulatedComponent: Uses ViewEncapsulation.Emulated to ensure its styles don't leak out.
ShadowDomComponent: Uses ViewEncapsulation.ShadowDom for true style isolation.
NoneComponent: Uses ViewEncapsulation.None, allowing its styles to affect other components.