All topics

Angular Interview Questions & Answers

40 questions with detailed answers — for freshers and experienced candidates.

Want to actually learn Angular?

Join a hands-on mini internship or training on iCampusLink and earn a certificate.

Explore programs →

Fresher Level

Q1. What is Angular and what are its key features?

Angular is a powerful, open-source front-end framework developed by Google for building single-page applications (SPAs) and complex web applications. It's written in TypeScript, a superset of JavaScript, which brings static typing and object-oriented features. Key features include: 1. **Component-based Architecture:** Applications are built as a tree of components, promoting reusability and maintainability. 2. **Two-way Data Binding:** Simplifies synchronization between the model and the view. 3. **Dependency Injection:** Manages component dependencies, making applications modular and testable. 4. **Routing:** Enables navigation between different views within the application. 5. **Angular CLI:** A command-line interface for scaffolding, developing, and deploying Angular applications. 6. **RxJS Integration:** Provides powerful tools for handling asynchronous data streams. 7. **TypeScript:** Enhances code quality, readability, and error detection during development.

Q2. Explain the concept of Components in Angular.

Components are the fundamental building blocks of an Angular application. Each component controls a specific part of the user interface (UI) and is composed of three main parts: 1. **Template (HTML):** Defines the view or UI structure. 2. **Class (TypeScript):** Contains the component's logic, data, and lifecycle methods. 3. **Metadata (Decorator):** An `@Component()` decorator provides essential configuration like the `selector` (how Angular finds the component in HTML), `templateUrl` or `template`, and `styleUrls` or `styles`. Components promote reusability, modularity, and maintainability by encapsulating specific functionalities and views.

Q3. What is a Module in Angular and why are they used?

An Angular Module (NgModules) is a cohesive block of code dedicated to a specific application domain, workflow, or a set of closely related capabilities. Every Angular application has at least one root module, conventionally named `AppModule`. Modules are used to: 1. **Organize Code:** They group components, services, pipes, and directives that belong together, making applications more manageable. 2. **Provide Context:** They declare which components, directives, and pipes belong to the module, and which services it makes available to other parts of the application. 3. **Encapsulation:** They can import functionality from other modules and export their own functionality for use by other modules. 4. **Lazy Loading:** Modules are essential for lazy loading, allowing parts of the application to be loaded only when needed, improving performance.

Q4. Describe the different types of data binding in Angular.

Angular supports several types of data binding to facilitate communication between the component's logic (TypeScript class) and its view (HTML template): 1. **Interpolation (`{{ }}`):** One-way binding from component to view. Displays a component property's value in the template. 2. **Property Binding (`[property]`):** One-way binding from component to view. Sets an HTML element's property to a component property's value. 3. **Event Binding (`(event)`):** One-way binding from view to component. Listens for events (e.g., `click`, `submit`) on HTML elements and executes a component method. 4. **Two-Way Data Binding (`[(ngModel)]`):** Binds both ways, synchronizing data from component to view and from view to component simultaneously. It's typically used with form elements and requires the `FormsModule`.

Q5. What are Directives in Angular? Differentiate between structural and attribute directives.

Directives are classes that add extra behavior to elements in Angular applications. They allow you to manipulate the DOM by changing its appearance, behavior, or structure. There are three main types: 1. **Components:** Directives with a template. 2. **Structural Directives:** Change the DOM layout by adding or removing elements. They are prefixed with an asterisk (`*`). Examples: `*ngIf`, `*ngFor`, `*ngSwitch`.
    <div *ngIf="isVisible">Content</div>
    
3. **Attribute Directives:** Change the appearance or behavior of an element, component, or another directive. They are applied as attributes to elements. Examples: `ngClass`, `ngStyle`, `ngModel`.
    <p [ngClass]="'highlight'">Text</p>
    
Structural directives fundamentally alter the DOM structure, while attribute directives only modify existing elements.

Q6. Explain Dependency Injection (DI) in Angular.

Dependency Injection (DI) is a core design pattern in Angular used to increase flexibility and modularity. It allows a class to receive its dependencies from an external source rather than creating them itself. In Angular, the DI system provides instances of services or objects to components or other services that declare them as dependencies. Angular's DI system works with: 1. **Providers:** Configure an injector to create a dependency. 2. **Injectors:** An object that creates and holds dependencies and can inject them into classes. 3. **Dependencies:** The services or objects that a class needs to function. This pattern makes components and services easier to test, maintain, and reuse by decoupling them from their dependencies.

Q7. What are Angular Pipes? Give an example.

Angular Pipes are simple functions used in templates to transform data before displaying it. They take an input value and return a transformed value, making it easy to format dates, currencies, text cases, and more without modifying the component's data. Pipes can be chained and parameterized. Angular provides built-in pipes like `DatePipe`, `CurrencyPipe`, `UpperCasePipe`, `LowerCasePipe`, and `DecimalPipe`. Developers can also create custom pipes. Example:
<p>Original date: {{ todayDate }}</p>
<p>Formatted date: {{ todayDate | date:'shortDate' }}</p>
<p>Price: {{ productPrice | currency:'USD':'symbol':'1.2-2' }}</p>
In this example, `date` and `currency` are pipes that transform `todayDate` and `productPrice` respectively. The `:'shortDate'` and `:'USD':'symbol':'1.2-2'` are pipe parameters.

Q8. List and explain some common Angular Lifecycle Hooks.

Angular components and directives have a lifecycle managed by Angular. Lifecycle hooks are special methods that allow you to tap into these key moments. Common hooks include: 1. **`ngOnChanges`:** Called when an input property changes. Useful for reacting to changes in `@Input()` properties. 2. **`ngOnInit`:** Called once after the component's data-bound properties are initialized. Ideal for fetching initial data from a service. 3. **`ngDoCheck`:** Called during every change detection cycle. Use it for custom change detection logic. 4. **`ngAfterContentInit`:** Called after Angular projects external content into the component's view. 5. **`ngAfterViewInit`:** Called after Angular initializes the component's views and child views. Useful for direct DOM manipulation or third-party library integration. 6. **`ngOnDestroy`:** Called just before Angular destroys the component. Use it for cleanup, such as unsubscribing from observables or detaching event handlers.

Q9. How does Angular Routing work?

Angular Routing allows navigation from one view to another within a single-page application without full page reloads. It maps URLs to specific components, enabling a rich user experience. Key concepts: 1. **`RouterModule`:** Provides the necessary routing capabilities. 2. **Routes:** An array of `Route` objects, each defining a path and the component to load for that path. 3. **`RouterOutlet`:** A directive that acts as a placeholder where Angular dynamically loads components based on the current route. 4. **`RouterLink`:** A directive used on anchor tags (`<a>`) to navigate to different routes programmatically or declaratively. When a user clicks a `RouterLink` or navigates to a URL, the Angular router matches the URL to a defined route, instantiates the corresponding component, and renders it within the `RouterOutlet`.

Q10. What is the purpose of Angular CLI?

The Angular CLI (Command Line Interface) is a powerful tool used to initialize, develop, scaffold, and maintain Angular applications. It streamlines the development process significantly. Its main purposes include: 1. **Project Generation:** Quickly creates a new Angular workspace and application (`ng new`). 2. **Scaffolding:** Generates components, services, modules, directives, pipes, etc., with best practices (`ng generate component my-component`). 3. **Development Server:** Provides a local development server with live reload (`ng serve`). 4. **Building:** Compiles the application into deployable artifacts (`ng build`). 5. **Testing:** Runs unit and end-to-end tests (`ng test`, `ng e2e`). 6. **Linting:** Helps maintain code quality and style (`ng lint`). 7. **Updating:** Updates Angular and its dependencies (`ng update`). The CLI automates many repetitive tasks, allowing developers to focus more on writing application logic.

Intermediate Level

Q1. Differentiate between Template-driven Forms and Reactive Forms.

Angular offers two approaches for building forms: Template-driven and Reactive forms. **Template-driven Forms:** * Logic primarily resides in the template using directives like `ngModel`. * Good for simple forms, quick prototyping. * Less programmatic control, harder to unit test. * Relies on two-way data binding. **Reactive Forms:** * Logic primarily resides in the component class using `FormControl`, `FormGroup`, `FormArray`. * Better for complex forms, dynamic forms, and validation. * More programmatic control, easier to unit test. * Relies on explicit data models and observables. Reactive forms offer more control, scalability, and testability, making them generally preferred for larger applications, while template-driven forms are simpler for basic use cases.

Q2. How do you communicate between components in Angular?

Component communication in Angular can be achieved in several ways: 1. **Parent to Child (`@Input()`):** Parent component passes data to a child component using property binding. The child component declares an `@Input()` property to receive the data.
    // Child component
    @Input() dataFromParent: string;
    
2. **Child to Parent (`@Output()` and `EventEmitter`):** Child component emits events that the parent component listens to. The child uses `@Output()` to expose an `EventEmitter` property.
    // Child component
    @Output() dataToParent = new EventEmitter<string>();
    emitData() { this.dataToParent.emit('Hello Parent!'); }
    
3. **Sibling/Unrelated Components (Services):** Components communicate via a shared service. The service holds data and provides methods to update/retrieve it, often using RxJS `Subjects` or `BehaviorSubjects` to broadcast changes. 4. **`ViewChild`/`ViewChildren` or `ContentChild`/`ContentChildren`:** Parent component can directly access child component instances or projected content elements.

Q3. Explain the role of `HttpClient` in Angular and how to make a GET request.

Angular's `HttpClient` is a service in the `@angular/common/http` module used to make HTTP requests to backend services. It offers a simplified API for interacting with HTTP, provides type-checking for request and response objects, and includes built-in features for error handling and interceptors. To use `HttpClient`, you must import `HttpClientModule` into your `AppModule`. Example of a GET request:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class DataService {
  constructor(private http: HttpClient) { }

  getUsers() {
    return this.http.get<any[]>('https://api.example.com/users');
  }
}
This service method returns an `Observable` of the response data. You would subscribe to this observable in a component to receive the data.

Q4. What are Observables in Angular (RxJS)? How do you subscribe to them?

Observables are a core concept in RxJS, a library that Angular uses extensively for handling asynchronous data streams. An Observable represents a stream of values or events over time. Unlike Promises, which handle a single asynchronous event, Observables can emit multiple values (0, 1, or many) over their lifetime. To consume values from an Observable, you `subscribe` to it. The `subscribe` method takes up to three callback functions: 1. **`next`:** Called for each value emitted by the Observable. 2. **`error`:** Called if an error occurs. 3. **`complete`:** Called when the Observable stream finishes.
import { of } from 'rxjs';

const myObservable = of(1, 2, 3);

myObservable.subscribe({
  next: value => console.log(value),
  error: err => console.error(err),
  complete: () => console.log('Completed!')
});
It's crucial to `unsubscribe` from long-lived Observables (e.g., HTTP requests, custom event listeners) in `ngOnDestroy` to prevent memory leaks.

Q5. Describe the concept of `ViewEncapsulation` in Angular.

`ViewEncapsulation` in Angular determines how the component's styles are applied and isolated from other components. It prevents styles defined in one component from bleeding into others, promoting modularity and preventing style conflicts. Angular offers three encapsulation strategies: 1. **`ViewEncapsulation.Emulated` (Default):** Angular adds unique attributes (`_ngcontent-cXY`) to component's host element and its descendant elements, then scopes the CSS rules using these attributes. This mimics Shadow DOM behavior without browser native support. 2. **`ViewEncapsulation.ShadowDom`:** Uses the browser's native Shadow DOM API to attach a shadow root to the component's host element. Styles are truly isolated within this shadow root. 3. **`ViewEncapsulation.None`:** No view encapsulation. Component styles are added to the global style sheet, meaning they can affect other components. Use with caution.
import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: '...', stylesheets: ['...'],
  encapsulation: ViewEncapsulation.Emulated // Default
})
export class MyComponent { }

Q6. What is Change Detection in Angular? Explain the `OnPush` strategy.

Change detection is the mechanism Angular uses to synchronize the application's data model with the view. When data changes (e.g., user interaction, HTTP response), Angular detects these changes and updates the DOM accordingly. By default, Angular uses the `Default` change detection strategy, which checks all components from top to bottom whenever any data might have changed. This can be inefficient for large applications. **`OnPush` Strategy:** With `OnPush` strategy, a component only runs change detection when: 1. One of its `@Input()` properties changes (by reference, not mutation). 2. It emits an event via an `@Output()`. 3. An observable it subscribes to emits a value (if using the `async` pipe). 4. Manually triggered (e.g., `ChangeDetectorRef.detectChanges()`). `OnPush` significantly improves performance by reducing the number of checks, as it assumes immutability for input properties. It requires careful handling of mutable objects.

Q7. How do you create a Custom Directive in Angular?

To create a custom attribute directive, you use the `@Directive()` decorator. This allows you to add custom behavior to existing DOM elements or components. Steps: 1. **Generate Directive:** Use Angular CLI: `ng generate directive highlight`. 2. **Define Selector:** In the `@Directive()` decorator, define a unique selector (e.g., `[appHighlight]`). This is how you'll apply the directive in HTML. 3. **Inject `ElementRef` and `Renderer2`:** Use `ElementRef` to get a reference to the host DOM element and `Renderer2` for safe DOM manipulation (recommended over direct `ElementRef.nativeElement` access). 4. **Implement Logic:** Use `@HostListener()` to listen for events on the host element (e.g., `mouseenter`, `mouseleave`) and `@HostBinding()` to bind to host element properties (e.g., `style.backgroundColor`).
import { Directive, ElementRef, HostListener, Input, Renderer2 } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor(private el: ElementRef, private renderer: Renderer2) { }

  @Input() appHighlight = 'yellow'; // Default color

  @HostListener('mouseenter') onMouseEnter() {
    this.renderer.setStyle(this.el.nativeElement, 'background-color', this.appHighlight);
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.renderer.setStyle(this.el.nativeElement, 'background-color', null);
  }
}

Q8. What are Route Guards and when would you use them?

Route Guards are interfaces that Angular provides to control navigation to or away from routes. They are functions that run before a route is activated or deactivated, allowing you to implement authorization, authentication, or prevent accidental navigation. Common Guard types: 1. **`CanActivate`:** Prevents navigation to a route unless certain conditions are met (e.g., user is logged in). 2. **`CanActivateChild`:** Protects child routes. 3. **`CanDeactivate`:** Prevents navigation away from a route (e.g., if a form has unsaved changes). 4. **`Resolve`:** Fetches data before the route is activated, ensuring data is available when the component loads. 5. **`CanLoad`:** Prevents a module from being lazy-loaded if conditions are not met, useful for security and performance. Guards return a `boolean`, `Observable<boolean>`, or `Promise<boolean>`.

Q9. Explain HTTP Interceptors in Angular. Provide a use case.

HTTP Interceptors are a powerful feature in Angular that allow you to intercept and modify HTTP requests and responses globally. They sit between your application and the backend, processing requests before they are sent and responses before they reach your code. To create an interceptor, you implement the `HttpInterceptor` interface, which has a single `intercept()` method. **Use Case: Adding an Authorization Header** Instead of manually adding an `Authorization` token to every `HttpClient` request, an interceptor can automatically attach it to all outgoing requests.
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authToken = localStorage.getItem('token'); // Get token
    const authReq = req.clone({ setHeaders: { Authorization: `Bearer ${authToken}` } });
    return next.handle(authReq);
  }
}
Interceptors are registered in the `AppModule`'s `providers` array.

Q10. What is the difference between Ahead-of-Time (AOT) and Just-in-Time (JIT) compilation in Angular?

Angular applications can be compiled in two ways: 1. **Just-in-Time (JIT) Compilation:** * Compilation happens in the browser at runtime. * The browser downloads the Angular compiler along with the application code. * The compiler then compiles the application's templates and components into JavaScript code before the browser renders them. * Typically used during development because it allows for faster rebuilds. 2. **Ahead-of-Time (AOT) Compilation:** * Compilation happens during the build process, before the browser loads the application. * The Angular compiler runs on the server (e.g., Node.js) and converts all Angular templates and components into plain JavaScript and HTML during the build step. * The browser then downloads a pre-compiled version of the application. * **Advantages:** Faster rendering, smaller application size (no compiler shipped), fewer asynchronous requests, better security, and earlier template error detection. * **Recommended for production builds.**

Q11. How do you handle errors in Angular applications, especially with `HttpClient`?

Error handling in Angular applications, particularly with `HttpClient` requests, is crucial for a robust user experience. For `HttpClient` requests, Observables emit errors via their `error` callback. You typically use the `catchError` operator from RxJS to intercept and handle these errors:
import { throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';

// In a service method calling HttpClient:
getUsers(): Observable<any[]> {
  return this.http.get<any[]>('/api/users').pipe(
    catchError(error => {
      console.error('An error occurred:', error);
      // Optionally, send error to a logging service
      return throwError(() => new Error('Something went wrong; please try again later.'));
    })
  );
}
For global error handling, Angular provides the `ErrorHandler` class. You can create a custom error handler that implements `ErrorHandler` and log errors to a service or display user-friendly messages. This catches errors not handled by `catchError` (e.g., component rendering errors).

Q12. What is `ngZone` and why is it important in Angular?

`ngZone` (specifically `Zone.js`) is a patching mechanism that wraps around standard asynchronous browser APIs (like `setTimeout`, `addEventListener`, `XMLHttpRequest`, Promises) to detect when asynchronous tasks start and finish. This allows Angular to know when to run its change detection cycle. Every Angular application runs inside an `NgZone` instance. When an asynchronous operation completes within this zone, `NgZone` notifies Angular, prompting it to check for changes in the application's data model and update the view if necessary. **Importance:** * **Automatic Change Detection:** It's the foundation for Angular's automatic change detection, removing the need for manual DOM manipulation or dirty checking. * **Performance Optimization:** In advanced scenarios, you might run code outside Angular's zone (`ngZone.runOutsideAngular()`) to prevent unnecessary change detection cycles, for example, with frequently updated third-party libraries or high-frequency events, then re-enter the zone (`ngZone.run()`) when interaction with Angular components is needed.

Q13. Explain the concept of Lazy Loading modules in Angular.

Lazy Loading is an optimization technique in Angular that loads NgModules only when they are needed, rather than loading them all at application startup. This significantly improves the initial load time of large applications by reducing the bundle size downloaded by the browser. Instead of importing all feature modules directly into the `AppModule`, lazy-loaded modules are configured in the routing. When a user navigates to a route associated with a lazy-loaded module, Angular dynamically fetches and loads that module and its components.
// app-routing.module.ts
const routes: Routes = [
  { 
    path: 'admin', 
    loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) 
  }
];
In this example, `AdminModule` will only be downloaded and parsed when the user navigates to `/admin`, making the initial load of the main application faster.

Q14. How do you optimize Angular application performance?

Optimizing Angular application performance involves several strategies: 1. **Lazy Loading Modules:** Load feature modules only when their routes are activated, reducing initial bundle size. 2. **OnPush Change Detection:** Use `ChangeDetectionStrategy.OnPush` for components to limit change detection checks, relying on immutable inputs. 3. **`trackBy` with `*ngFor`:** Improves rendering performance for lists by helping Angular track items uniquely, preventing re-rendering of the entire list. 4. **AOT Compilation:** Compiles templates and components into JavaScript ahead of time, leading to faster rendering and smaller bundles. 5. **Tree-shaking:** Removes unused code during the build process. 6. **Minification and Bundling:** Reduces file sizes. 7. **Server-Side Rendering (Angular Universal):** Improves initial load time and SEO. 8. **Web Workers:** Offload heavy computations to a background thread. 9. **Virtual Scrolling:** For large lists, renders only visible items. 10. **Debouncing/Throttling:** For frequent events like input or scroll, use RxJS operators to limit execution.

Q15. What is Content Projection in Angular? Explain `ng-content`.

Content Projection (also known as transclusion) is a mechanism in Angular for inserting content from the parent component's template directly into a child component's template. This allows components to be more flexible and reusable by letting their users provide the content they want to display inside the component. It's achieved using the `<ng-content>` element in the child component's template. The content placed between the child component's tags in the parent's template will be 'projected' into the `<ng-content>` slot. **Example:**
<!-- Parent component template -->
<app-card>
  <h2>Card Title</h2>
  <p>Some card content.</p>
</app-card>

<!-- Child (app-card) component template -->
<div class="card">
  <ng-content></ng-content>
</div>
Angular also supports `select` attributes on `ng-content` for multi-slot content projection, allowing specific content to be projected into specific slots based on CSS selectors.

Q16. Describe the role of `trackBy` function in `*ngFor` directive.

The `*ngFor` directive is used to render a list of items. When the list data changes (e.g., items are added, removed, or reordered), Angular's default behavior is to destroy and re-create all DOM elements for the list. This can be inefficient, especially for large lists, leading to performance issues and loss of component state (like scroll position or input focus). The `trackBy` function provides a hint to Angular about how to track changes to items in an `*ngFor` list. Instead of tracking by object identity, you provide a function that returns a unique identifier for each item. When the list changes, Angular uses this identifier to determine which items have been added, removed, or moved, and only re-renders the DOM elements that have actually changed.
// Component class
items = [{id: 1, name: 'A'}, {id: 2, name: 'B'}];
trackByItemId(index: number, item: any): number { return item.id; }

// Template
<div *ngFor="let item of items; trackBy: trackByItemId">
  {{ item.name }}
</div>
This significantly improves performance for dynamic lists.

Advanced Level

Q1. What is Angular Universal and what problem does it solve?

Angular Universal is a technology that enables Server-Side Rendering (SSR) for Angular applications. By default, Angular applications are rendered client-side in the browser, meaning an empty HTML page is sent, and JavaScript then builds the UI. **Problems Solved by Angular Universal:** 1. **Improved SEO:** Search engine crawlers can easily index pre-rendered content, as they see a fully rendered page, not just an empty HTML shell. 2. **Faster Initial Page Load:** Users see the first meaningful paint sooner, as the HTML is delivered fully formed. This improves perceived performance and user experience, especially on slow networks or devices. 3. **Better User Experience on First Load:** The application appears much faster, and content is visible before the JavaScript bundle fully loads and becomes interactive. Universal renders the application on a Node.js server, generating static HTML pages that are then sent to the browser. The client-side Angular application then 'hydrates' this static content, taking over interactivity.

Q2. Discuss different strategies for state management in Angular applications.

Managing application state effectively is crucial for complex Angular applications. Several strategies exist: 1. **Component-level State:** Simplest for small apps. State is managed within individual components using properties, often passed via `@Input()` and `@Output()`. 2. **Service-based State:** A common pattern where a shared service holds and manages state. Components inject the service and subscribe to RxJS `Subjects` or `BehaviorSubjects` exposed by the service to get state updates. This centralizes state logic and is suitable for medium-sized applications. 3. **RxJS-based State Management (e.g., NgRx):** Implements the Redux pattern. State is immutable and stored in a single store. Changes occur through dispatching `Actions`, which are handled by `Reducers` to produce new state. `Effects` handle side effects (e.g., API calls). `Selectors` query the state. Provides predictable state changes, great for large, complex applications, but has a learning curve. 4. **Other Libraries (e.g., Akita, NGXS):** Offer alternative state management patterns, often with less boilerplate than NgRx, aiming for simplicity while retaining benefits of centralized state.

Q3. How can you implement dynamic components in Angular?

Dynamic components are components that are loaded and rendered at runtime, rather than being declared statically in a template. This is useful for building dashboards, plugin systems, or situations where the UI structure is not known at compile time. To implement dynamic components: 1. **`ComponentFactoryResolver`:** This service is used to find the `ComponentFactory` for a component. A `ComponentFactory` is a class that knows how to create instances of a specific component. 2. **`ViewContainerRef`:** Represents a container where one or more views can be attached. It's often obtained via `@ViewChild` on an `<ng-container>` or `<div>` element. 3. **`createComponent()`:** The `ViewContainerRef`'s `createComponent()` method uses the `ComponentFactory` to instantiate the component and insert it into the DOM.
import { Component, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { MyDynamicComponent } from './my-dynamic.component';

@Component({ /* ... */ })
export class HostComponent {
  @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;

  constructor(private resolver: ComponentFactoryResolver) { }

  loadComponent() {
    const factory = this.resolver.resolveComponentFactory(MyDynamicComponent);
    this.container.clear(); // Clear previous components
    const componentRef = this.container.createComponent(factory);
    // You can interact with componentRef.instance here
  }
}
For Angular versions prior to 9, dynamic components needed to be explicitly listed in the `entryComponents` array of an `NgModule`. From Angular 9 onwards, this is no longer required as the Ivy compiler automatically identifies and includes dynamically instantiated components, provided they are declared in an `NgModule`.

Q4. Explain the concept of Web Workers and how they can be used in Angular.

Web Workers allow JavaScript to run scripts in a background thread, separate from the main UI thread. This prevents long-running or computationally intensive tasks from blocking the UI, keeping the application responsive. Since JavaScript is single-threaded in the browser, Web Workers provide a way to achieve parallel execution. **How to use in Angular:** 1. **Create a Worker:** Use Angular CLI: `ng generate web-worker my-worker`. 2. **Worker Script (`my-worker.worker.ts`):** Contains the heavy computation logic. It communicates with the main thread using `postMessage()` and listens for messages via `self.onmessage`. 3. **Main Thread (Component/Service):** Creates an instance of the `Worker` and sends/receives messages.
// In a component/service
const worker = new Worker(new URL('./my-worker.worker', import.meta.url));
worker.onmessage = ({ data }) => {
  console.log('Worker response:', data);
};
worker.postMessage({ type: 'calculate', payload: 1000000 });
Web Workers are ideal for tasks like complex calculations, image processing, or large data manipulations that would otherwise freeze the UI.

Q5. What are Angular Schematics? Give an example of their utility.

Angular Schematics are a workflow tool for the Angular CLI that allow you to generate, modify, and update code in a consistent and automated way. They are essentially code generators that operate on a file system tree (in-memory or real) and can perform various transformations. **Utility:** 1. **Code Scaffolding:** `ng generate component` or `ng generate service` are built using schematics. They create new files, add boilerplate code, and update related files (e.g., registering components in `AppModule`). 2. **Library Development:** Schematics are crucial for creating shareable Angular libraries, providing CLI commands for users to add your library, generate its components, or update it. 3. **Code Refactoring/Migration:** They can automate large-scale code changes, like updating deprecated API usage across an entire codebase during an Angular version upgrade. 4. **Custom Workflows:** Developers can create custom schematics to enforce project standards, integrate third-party libraries, or automate any repetitive code-related tasks specific to their project or organization.

Q6. How do you approach testing in Angular? Briefly describe unit and end-to-end testing.

Testing is an integral part of Angular development, ensuring application quality and stability. Angular CLI sets up a testing environment with Karma (for unit testing) and Protractor (for end-to-end testing), though Cypress is a popular alternative for E2E. 1. **Unit Testing:** * Tests individual units of code in isolation (e.g., components, services, pipes, directives). * Uses testing frameworks like Jasmine (for writing tests) and Karma (for running them in browsers). * Focuses on the logic and behavior of a single class or function. * Mocks dependencies to isolate the unit under test.
    // Example: service unit test
    describe('UserService', () => {
      let service: UserService;
      beforeEach(() => { TestBed.configureTestingModule({}); service = TestBed.inject(UserService); });
      it('should be created', () => { expect(service).toBeTruthy(); });
    });
    
2. **End-to-End (E2E) Testing:** * Tests the entire application flow from a user's perspective, simulating user interactions. * Verifies that different parts of the application work together correctly. * Protractor (or Cypress) runs tests in a real browser, interacting with the deployed application. * Focuses on user scenarios like login, form submission, and navigation. Both types of testing are crucial for a comprehensive testing strategy.

Q7. Explain different RxJS operators for transforming and filtering data.

RxJS operators are pure functions that enable declarative, reactive programming by transforming, filtering, or combining Observables. They allow powerful manipulation of data streams. **Transforming Operators:** * **`map()`:** Applies a projection function to each value emitted by the source Observable and emits the result. `map(x => x * 2)` * **`pluck()`:** Extracts a specific property from each emitted object. `pluck('name')` * **`scan()`:** Applies an accumulator function over the source Observable, and returns each intermediate result. Similar to `reduce` but emits values after each accumulation. `scan((acc, val) => acc + val, 0)` **Filtering Operators:** * **`filter()`:** Emits only those values from the source Observable that satisfy a specified predicate function. `filter(x => x % 2 === 0)` * **`take()`:** Emits only the first `N` values emitted by the source Observable, then completes. `take(5)` * **`debounceTime()`:** Delays emitting values from the source Observable until a specified duration has passed without another source emission. Useful for search inputs. `debounceTime(300)` * **`distinctUntilChanged()`:** Emits all values that are distinct from the previous value emitted. `distinctUntilChanged()`

Q8. What are Higher-Order Observables and operators like `switchMap`, `mergeMap`, `concatMap`?

A Higher-Order Observable is an Observable that emits other Observables. This commonly occurs when an asynchronous operation (e.g., an HTTP request) needs to be triggered based on another asynchronous event (e.g., a button click or another HTTP response). **Flattening Operators** (or Higher-Order Mapping Operators) are used to 'flatten' these nested Observables into a single, simpler Observable stream: 1. **`mergeMap` (or `flatMap`):** Subscribes to all inner Observables concurrently. Emissions from inner Observables are merged into the output Observable as they arrive. Good when order doesn't matter and you want parallel execution. 2. **`switchMap`:** Subscribes to an inner Observable and unsubscribes from the previous inner Observable whenever a new value is emitted by the source. Ideal for 'type-ahead' search, where you only care about the latest request and want to cancel previous, slower requests. 3. **`concatMap`:** Subscribes to inner Observables one after another, in the order they are created. It waits for the current inner Observable to complete before subscribing to the next. Good when order is important and you need to process sequentially. 4. **`exhaustMap`:** Ignores new source values while the current inner Observable is still active. It's useful for preventing multiple clicks on a button from triggering multiple API calls while one is already in progress.

Q9. Describe how to implement server-side rendering (SSR) with Angular Universal.

Implementing SSR with Angular Universal involves several steps to set up a Node.js server to pre-render your Angular application. 1. **Add Universal to Project:** Use the Angular CLI: `ng add @nguniversal/express-engine`. This command adds necessary dependencies, generates `server.ts` (the Node.js server file), `main.server.ts` (the server-side entry point), and updates `angular.json`. 2. **Build Configuration:** The CLI command configures two new build targets: `build:ssr` for server-side compilation and `serve:ssr` for running the SSR server. 3. **`server.ts`:** This file sets up an Express.js server that serves the static assets and handles requests for Angular routes by rendering the application on the server using `ngExpressEngine`. 4. **`main.server.ts`:** This is the entry point for the server-side application. It exports an `AppServerModule` which bootstraps your root `AppModule` in a server environment. When a request comes in, the Node.js server renders the Angular app to HTML, sends that HTML to the browser, and then the client-side Angular app takes over (hydration). This provides a fast initial load and improved SEO.

Q10. How do you secure an Angular application against common web vulnerabilities?

Securing an Angular application involves multiple layers, addressing both client-side and backend vulnerabilities: 1. **Cross-Site Scripting (XSS):** Angular automatically sanitizes values when binding to HTML, preventing XSS. Always use Angular's templates and property binding. Be cautious with `[innerHTML]`, `DomSanitizer`, and direct DOM manipulation. 2. **Cross-Site Request Forgery (CSRF):** Rely on backend frameworks to implement CSRF protection (e.g., anti-forgery tokens). Angular's `HttpClient` supports `XSRF-TOKEN` headers. 3. **Authentication & Authorization:** Implement secure authentication (e.g., JWT, OAuth 2.0) and authorization (role-based access control) using route guards and backend validation. 4. **HTTPS:** Always use HTTPS to encrypt communication. 5. **Sanitization & Validation:** Validate all user inputs on both client and server sides. Sanitize data received from APIs before displaying. 6. **Dependency Updates:** Regularly update Angular and third-party libraries using `ng update` to patch known vulnerabilities. 7. **Content Security Policy (CSP):** Configure CSP headers to restrict resources (scripts, styles) that the browser is allowed to load. 8. **Avoid `eval()` and `new Function()`:** These can introduce security risks.

Q11. What is `Renderer2` and when would you use it instead of direct DOM manipulation?

`Renderer2` is an abstraction layer in Angular that provides a safe way to interact with the DOM, allowing you to manipulate elements without directly accessing the `nativeElement` of `ElementRef`. Direct DOM manipulation can be problematic because: 1. **Security Risks:** It can expose your application to XSS attacks. 2. **Platform Independence:** Angular applications can run on different platforms (browser, web worker, server-side rendering). Direct DOM access is browser-specific and won't work in other environments. 3. **Testing:** Direct DOM manipulation makes components harder to test. **When to use `Renderer2`:** * When you need to perform low-level DOM operations that aren't covered by Angular's data binding (e.g., adding/removing classes, setting styles, creating/destroying elements). * To ensure your application remains platform-agnostic. * To maintain security best practices.
import { Component, ElementRef, Renderer2, ViewChild } from '@angular/core';

@Component({ /* ... */ })
export class MyComponent {
  @ViewChild('myDiv') myDiv: ElementRef;

  constructor(private renderer: Renderer2) { }

  ngAfterViewInit() {
    this.renderer.setStyle(this.myDiv.nativeElement, 'background-color', 'blue');
    this.renderer.addClass(this.myDiv.nativeElement, 'highlight');
  }
}

Q12. Explain the concept of a Monorepo in the context of Angular development, particularly with Nx.

A monorepo (monolithic repository) is a single version control repository that holds multiple distinct projects, often with shared code. In Angular development, monorepos are increasingly popular for managing large applications or multiple related applications and libraries within one codebase. **Benefits:** * **Code Sharing:** Easy to share code (e.g., UI components, utility services) between projects. * **Atomic Changes:** A single commit can update multiple projects and shared libraries simultaneously, ensuring consistency. * **Simplified Refactoring:** Changes in shared code can be easily propagated and tested across all dependent projects. * **Consistency:** Enforces consistent tooling, dependencies, and code style across all projects. **Nx (Nrwl Extensions):** Nx is a powerful toolkit for monorepo development, especially for Angular. It extends the Angular CLI with advanced features: * **Workspace Generation:** Sets up a monorepo structure with multiple applications and libraries. * **Dependency Graph:** Understands project dependencies, allowing for optimized builds and tests. * **Code Generation:** Provides specialized schematics for generating applications, libraries, and components within the monorepo. * **Code Sharing:** Encourages modularization into shareable libraries. * **Build Optimization:** Only rebuilds/retests affected projects after changes. Nx significantly simplifies the complexities of managing a large-scale Angular monorepo, promoting scalability and maintainability.

Q13. How does Angular's Dependency Injection system handle providers across different modules and components?

Angular's DI system uses a hierarchical injector tree, which allows for different scopes of providers and efficient tree-shaking. 1. **Module-level Providers:** * **`providedIn: 'root'`:** Services declared with `providedIn: 'root'` are provided at the root injector level. This creates a single, application-wide singleton instance of the service, which is accessible throughout the app. This is the preferred way for most services as it enables tree-shaking. * **`providers` array in `@NgModule`:** Services listed here are scoped to that module. If the module is lazy-loaded, the service becomes a singleton within that lazy-loaded module. If the module is eagerly loaded, the service becomes a singleton application-wide. Be careful with eagerly loaded modules providing services this way, as it can lead to multiple instances if imported by multiple eager modules. 2. **Component-level Providers:** * **`providers` array in `@Component`:** Services listed here are scoped to that specific component instance and its children. Each new instance of the component gets its own instance of the service. This is useful for component-specific state or resources. Angular resolves dependencies by traversing the injector tree upwards from the requesting component/service until it finds a provider. This hierarchy allows for overriding services at different levels and enables efficient resource management.

Q14. What are Micro Frontends and how can Angular be used to build them?

Micro Frontends are an architectural style where a large, monolithic frontend application is broken down into smaller, independently deployable frontend applications. Each micro frontend is owned by a separate team, can be developed and deployed independently, and communicates with others via well-defined interfaces. This improves scalability, agility, and team autonomy. **Angular's Role in Micro Frontends:** Angular can be used to build micro frontends, typically through: 1. **Angular Elements:** Angular components can be compiled into custom elements (Web Components). These can then be integrated into any host application (even non-Angular ones) using standard HTML tags, without requiring the host to be an Angular app itself. This provides strong encapsulation.
    import { createCustomElement } from '@angular/elements';
    import { Injector } from '@angular/core';

    // In AppModule's ngDoBootstrap
    const el = createCustomElement(MyAngularComponent, { injector: this.injector });
    customElements.define('my-angular-element', el);
    
2. **Module Federation (Webpack 5):** This feature allows different applications (federated modules) to dynamically load code from each other at runtime. An Angular application can expose parts of itself (components, services, modules) as remote modules, and another Angular application can consume them. This provides a more integrated approach than Web Components for Angular-to-Angular communication within a micro frontend architecture. Both approaches facilitate building complex UIs by composing smaller, independent Angular applications.
Prepared by iCampusLink. 40 Angular interview questions.
Top 40 Angular Interview Questions & Answers (2026) | iCampusLink