Question Mentor Logo Question Mentor
Practice With AI
Home » Directory » Interview Preparation » 150 Top-Asked Angular Interview Questions And Answers in 2026

150 Top-Asked Angular Interview Questions And Answers in 2026

After over a decade of building enterprise apps with Angular and mentoring dozens of developers through technical interviews, I’ve seen how the framework’s evolution directly shapes hiring expectations.

While React leads in popularity (~40% market share), Angular still powers over 360,000 websites globally and holds steady at ~17–18% adoption among professional developers.

I recently reviewed 12 major Angular interview guides published this year and found a clear pattern: hybrid questions combining Signals with RxJS, testing strategies for standalone apps, and migration tactics from v14 to v19 dominate the top 150 most-asked Angular interview questions in 2026. It’s no longer about syntax; it’s about architectural judgment.

Here are 150 Top-Asked Angular Interview Questions

150 Top Asked Angular Interview Questions in 2026

1. Why were client-side frameworks like Angular introduced?

Client-side frameworks like Angular were introduced to address the growing complexity of building modern web applications. Traditionally, web applications relied heavily on server-side rendering, where each user interaction required a full page reload. This approach was inefficient, slow, and led to a poor user experience, especially as applications became more interactive and data-driven.

With the rise of Single Page Applications (SPAs), developers needed a way to create dynamic, responsive, and seamless user experiences without constant server requests. Client-side frameworks like Angular enable developers to build applications where most of the logic and rendering happens in the browser. This reduces server load, improves performance, and provides a smoother user experience by updating only the necessary parts of the page.

Angular, in particular, was designed to simplify the development of SPAs by providing a structured, modular approach. It introduced features like two-way data binding, dependency injection, and component-based architecture, which made it easier to manage complex applications. Additionally, Angular’s integration with TypeScript brought static typing and better tooling, further enhancing developer productivity.

2. How does an Angular application work?

An Angular application is built around a component-based architecture, where the application is divided into reusable and modular components. Here’s a high-level overview of how it works:

  1. Bootstrapping: When an Angular application starts, it bootstraps the root component (usually AppComponent). This component is defined in the main.ts file and serves as the entry point of the application.
  2. Component Rendering: Angular renders the root component and its template (HTML) into the DOM. The template defines the view, while the component class contains the logic and data.
  3. Data Binding: Angular uses data binding to synchronize the data between the component class and the view. For example, if a variable in the component changes, the view automatically updates to reflect that change.
  4. Dependency Injection: Angular’s dependency injection (DI) system provides the necessary services and dependencies to components. This promotes modularity and reusability.
  5. Routing: The Angular Router enables navigation between different views or components without reloading the page. This is essential for creating SPAs.
  6. State Management: For complex applications, Angular can integrate with state management libraries like NgRx to manage application state efficiently.

In summary, Angular applications are dynamic, modular, and efficient, leveraging components, templates, and services to create a seamless user experience.

3. What are some of the advantages of Angular over other frameworks?

Angular offers several advantages over other frameworks, making it a popular choice for building complex web applications:

  • Full-Fledged Framework: Angular is a complete framework, providing built-in solutions for routing, HTTP client, forms, and more. This reduces the need for third-party libraries.
  • TypeScript Support: Angular is built with TypeScript, which offers static typing, better tooling, and improved maintainability compared to JavaScript.
  • Two-Way Data Binding: Angular’s two-way data binding simplifies synchronization between the model and the view, reducing boilerplate code.
  • Modularity: Angular’s modular architecture allows developers to organize code into reusable modules, making it easier to scale and maintain large applications.
  • Dependency Injection: Angular’s built-in dependency injection system promotes modularity and testability by managing dependencies efficiently.
  • Strong Ecosystem: Angular has a robust ecosystem with tools like Angular CLI, which simplifies project setup, testing, and deployment.
  • Performance Optimization: Features like Ahead-of-Time (AOT) compilation and lazy loading improve application performance.

These advantages make Angular a powerful choice for enterprise-level applications where scalability, maintainability, and performance are critical.

4. What are the advantages of Angular over React?

While both Angular and React are popular for building modern web applications, Angular offers several distinct advantages:

  • Complete Framework: Angular is a full-fledged framework, providing built-in solutions for routing, forms, HTTP client, and more. React, on the other hand, is a library and requires additional libraries for these features.
  • Two-Way Data Binding: Angular’s two-way data binding simplifies synchronization between the model and the view, whereas React relies on one-way data binding and requires manual state management.
  • TypeScript Support: Angular is built with TypeScript, which offers static typing and better tooling. React can use TypeScript, but it is optional.
  • Dependency Injection: Angular’s built-in dependency injection system makes it easier to manage dependencies and promotes modularity.
  • Structured Approach: Angular enforces a structured approach with modules, components, and services, which can be beneficial for large-scale applications.
  • Built-in Directives: Angular provides powerful built-in directives like *ngIf and *ngFor, which simplify common tasks.

While React offers flexibility and a lighter footprint, Angular’s comprehensive feature set and structured approach make it a strong choice for enterprise applications.

5. List out differences between AngularJS and Angular?

AngularJS and Angular are fundamentally different, despite sharing the same name. Here are the key differences:

Feature AngularJS Angular
Language JavaScript TypeScript
Architecture MVC (Model-View-Controller) Component-Based
Data Binding Two-Way (using $scope) Two-Way (using [(ngModel)])
Performance Slower due to dirty checking Faster with change detection
Dependency Injection Limited Hierarchical and modular
Mobile Support Limited Built-in mobile support
Routing ngRoute @angular/router

Angular is a complete rewrite of AngularJS, offering improved performance, better tooling, and a more modern architecture.

6. How are Angular expressions different from JavaScript expressions?

Angular expressions and JavaScript expressions serve similar purposes but have key differences:

  • Context: Angular expressions are evaluated within the context of the Angular framework, typically within templates. JavaScript expressions are evaluated in the global JavaScript context.
  • Syntax: Angular expressions use {{ expression }} syntax within templates, while JavaScript expressions are written directly in JavaScript code.
  • Forgiving: Angular expressions are more forgiving. For example, {{ 1 + undefined }} evaluates to 1 in Angular, whereas the same expression in JavaScript would result in NaN.
  • No Control Flow: Angular expressions do not support control flow statements like if, for, or while. JavaScript expressions can include these.
  • Filters: Angular expressions support filters (e.g., {{ name | uppercase }}), which are not available in JavaScript expressions.

Angular expressions are designed to be simple and safe for use in templates, while JavaScript expressions offer full programming flexibility.

7. What are Single Page Applications (SPA)?

A Single Page Application (SPA) is a web application that loads a single HTML page and dynamically updates the content as the user interacts with the app. Unlike traditional multi-page applications, SPAs do not require a full page reload during navigation, resulting in a faster and more seamless user experience.

SPAs achieve this by using JavaScript frameworks like Angular, React, or Vue.js to handle routing and rendering on the client side. When a user navigates to a different section of the app, the SPA fetches only the necessary data from the server and updates the view accordingly.

Key benefits of SPAs include:

  • Faster navigation and smoother user experience.
  • Reduced server load, as only data is fetched, not entire pages.
  • Better separation of concerns between the front-end and back-end.

However, SPAs can have challenges with SEO and initial load times, which need to be addressed with techniques like server-side rendering (SSR) or static site generation (SSG).

8. What are templates in Angular?

In Angular, a template is an HTML view that defines how a component is rendered in the browser. Templates combine standard HTML with Angular-specific syntax, such as directives, bindings, and pipes, to create dynamic and interactive user interfaces.

Templates are associated with components and define the structure and layout of the component’s view. They can include:

  • Data Bindings: To display component properties and handle user input (e.g., {{ user.name }}).
  • Directives: To add dynamic behavior (e.g., *ngIf, *ngFor).
  • Event Bindings: To respond to user actions (e.g., (click)="onClick()").
  • Pipes: To transform data before displaying it (e.g., {{ date | date }}).

Templates are compiled by Angular into efficient JavaScript code, which updates the DOM dynamically based on changes in the component’s data.

9. What are directives in Angular?

In Angular, directives are instructions that extend HTML by adding custom behavior to elements. Directives allow developers to create dynamic and reusable components, manipulate the DOM, and apply conditional logic or loops.

There are three types of directives in Angular:

  1. Component Directives: These are directives with a template and define a view. Components are the most common type of directive and are used to build the UI.
  2. Structural Directives: These directives change the DOM layout by adding or removing elements. Examples include *ngIf and *ngFor.
  3. Attribute Directives: These directives change the appearance or behavior of an element. Examples include ngClass and ngStyle.

Directives are a powerful feature in Angular, enabling developers to create highly interactive and dynamic user interfaces with minimal code.

11. What is the scope?

In programming, particularly in frameworks like AngularJS, the term scope refers to the binding part between the HTML (view) and the JavaScript (controller). The scope is an object that contains the application data and methods. It acts as a context for evaluating expressions and serves as the glue between the view and the controller.

In AngularJS, the $scope object is used to bind data between the view and the controller. For example, if you define a variable in the controller and attach it to the $scope, it becomes accessible in the view. This allows for dynamic updates to the UI when the data changes.

Note: In modern Angular (Angular 2+), the concept of $scope has been replaced with a component-based architecture where data binding is handled directly within components.

12. What is data binding in Angular?

Data binding in Angular is a mechanism that synchronizes the data between the model (component) and the view (template). It ensures that any changes in the model are reflected in the view and vice versa, without manual intervention. Angular supports several types of data binding:

  • Interpolation ({{ data }}): Binds data from the component to the view.
  • Property Binding ([property]="data"): Binds a property of an HTML element to a component property.
  • Event Binding ((event)="handler()"): Binds an event (e.g., click) to a component method.
  • Two-Way Binding ([(ngModel)]="data"): Combines property and event binding to keep the model and view in sync.

Data binding simplifies the process of keeping the UI up-to-date with the application state, making Angular applications dynamic and responsive.

13. What is two-way data binding in Angular?

Two-way data binding in Angular is a powerful feature that allows automatic synchronization between the model (component) and the view (template). This means that any changes in the model are immediately reflected in the view, and any changes in the view (e.g., user input) are automatically updated in the model.

Two-way data binding is achieved using the [(ngModel)] directive. For example:


<input [(ngModel)]="userName" placeholder="Enter your name">
<p>Hello, {{ userName }}!</p>
        

In this example, typing in the input field updates the userName property in the component, and the paragraph displays the updated value in real-time.

Note: To use ngModel, you need to import the FormsModule from @angular/forms in your Angular module.

14. What are Decorators and their types in Angular?

In Angular, decorators are special functions that modify or enhance the behavior of classes, methods, or properties. They are a core part of TypeScript and are widely used in Angular to define metadata for components, directives, services, and more.

Here are the common types of decorators in Angular:

  • @Component: Defines a class as an Angular component. It includes metadata like the template, styles, and selector.
  • @Directive: Defines a class as an Angular directive, which can modify the behavior of elements.
  • @Injectable: Marks a class as a service that can be injected into other components or services.
  • @Input and @Output: Used to define input and output properties in components for parent-child communication.
  • @NgModule: Defines a class as an Angular module, which groups related components, directives, and services.

Decorators provide a way to add metadata and configure how Angular processes and uses classes, making them a fundamental part of Angular’s architecture.

15. What are annotations in Angular?

In Angular, annotations are a way to attach metadata to classes. They are similar to decorators but are specifically used to provide additional information to the Angular compiler about how a class should be processed. Annotations are typically defined using the @ symbol followed by the annotation name.

For example, the @Component decorator is an annotation that tells Angular that a particular class is a component and provides metadata like the selector, template, and styles. Annotations help Angular understand the role and behavior of classes during compilation and runtime.

While the terms “decorators” and “annotations” are often used interchangeably in Angular, annotations specifically refer to the metadata attached to classes.

16. What are pure Pipes?

In Angular, a pure pipe is a type of pipe that is executed only when Angular detects a change in the input data. Pure pipes are stateless, meaning they produce the same output for the same input and do not rely on any internal state or external factors.

Pure pipes are optimized for performance because Angular only recalculates their output when their input values change. This makes them ideal for transformations that are computationally expensive or do not need to be recalculated frequently.

By default, all pipes in Angular are pure. Here’s an example of a pure pipe:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'uppercasePipe' })
export class UppercasePipe implements PipeTransform {
  transform(value: string): string {
    return value.toUpperCase();
  }
}
        

17. What are impure pipes?

An impure pipe in Angular is a pipe that is executed during every change detection cycle, regardless of whether the input data has changed. Impure pipes are marked with the pure: false option in their metadata.

Impure pipes are useful when you need to transform data that depends on factors other than the input values, such as global state or external data. However, they can impact performance because they are recalculated frequently.

Here’s an example of an impure pipe:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'impurePipe',
  pure: false
})
export class ImpurePipe implements PipeTransform {
  transform(value: any): any {
    return `Impure: ${value}`;
  }
}
        

Note: Use impure pipes sparingly, as they can lead to performance issues if overused.

18. What is PipeTransform Interface in Angular?

The PipeTransform interface in Angular is used to define custom pipes. It requires the implementation of a single method, transform, which takes an input value and optional arguments, and returns a transformed value.

Here’s how you can create a custom pipe using the PipeTransform interface:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'reversePipe' })
export class ReversePipe implements PipeTransform {
  transform(value: string): string {
    return value.split('').reverse().join('');
  }
}
        

In this example, the ReversePipe reverses the input string. The transform method is called whenever the pipe is used in a template.

19. Write a code where you have to share data from the Parent to Child Component?

To share data from a parent component to a child component in Angular, you can use the @Input decorator. Here’s an example:


// Parent Component
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <app-child [childMessage]="parentMessage"></app-child>
  `
})
export class ParentComponent {
  parentMessage = "Hello from Parent!";
}
        

// Child Component
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<p>{{ childMessage }}</p>`
})
export class ChildComponent {
  @Input() childMessage: string;
}
        

In this example, the parent component passes the parentMessage to the child component using property binding. The child component receives the data via the @Input decorator.

20. Create a TypeScript class with a constructor and a function.

Here’s an example of a TypeScript class with a constructor and a function:


class Person {
  private name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet(): string {
    return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
  }
}

// Usage
const person = new Person("Faheem", 30);
console.log(person.greet()); // Output: Hello, my name is Faheem and I am 30 years old.
        

In this example, the Person class has a constructor to initialize the name and age properties, and a greet function to return a greeting message.

21. Explain MVVM architecture.

MVVM (Model-View-ViewModel) is an architectural pattern commonly used in modern web and mobile applications, including Angular. It separates the application into three main components:

  • Model: Represents the data and business logic of the application. It is responsible for managing the data, including fetching, storing, and manipulating it.
  • View: Represents the user interface (UI) of the application. It displays the data from the ViewModel and sends user actions (like clicks or inputs) to the ViewModel.
  • ViewModel: Acts as an intermediary between the Model and the View. It exposes data from the Model to the View and handles user interactions by updating the Model. The ViewModel also contains logic for transforming data from the Model into a format that the View can easily consume.

In Angular, the ViewModel is typically represented by the component class, which binds data to the view (template) and handles user interactions. The Model is often managed by services, and the View is defined by the component’s template.

MVVM promotes a clean separation of concerns, making applications easier to maintain, test, and scale.

22. What is a bootstrapping module?

In Angular, the bootstrapping module is the root module that initializes the application. It is the entry point of the application and is responsible for launching the root component. The bootstrapping process involves loading the necessary modules, components, and services required to start the application.

The bootstrapping module is typically defined in the app.module.ts file. Here’s an example:


import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  bootstrap: [AppComponent]
})
export class AppModule {}
        

In this example, AppModule is the bootstrapping module, and AppComponent is the root component that gets bootstrapped when the application starts.

23. What is Change Detection, and how does the Change Detection Mechanism work?

Change Detection in Angular is the mechanism by which the framework detects changes in the application’s data and updates the DOM accordingly. It ensures that the view is always synchronized with the model.

Angular uses a Change Detection Mechanism based on zones. Here’s how it works:

  1. Zone.js: Angular uses Zone.js to detect asynchronous operations (like user events, timers, or HTTP requests) that might change the application state.
  2. Change Detection Cycle: When an asynchronous event occurs, Zone.js triggers Angular’s change detection cycle. During this cycle, Angular checks all components to see if their data has changed.
  3. Update the View: If a change is detected, Angular updates the affected parts of the DOM to reflect the new state.

Angular provides two strategies for change detection:

  • Default Strategy: Checks all components for changes.
  • OnPush Strategy: Only checks components when their input properties change or when an event is triggered within the component.

24. What is AOT compilation? What are the advantages of AOT?

AOT (Ahead-of-Time) Compilation in Angular is the process of compiling Angular applications during the build phase, before they are deployed to the browser. This is in contrast to JIT (Just-in-Time) compilation, where the application is compiled in the browser at runtime.

Advantages of AOT:

  • Faster Rendering: The browser downloads a pre-compiled version of the application, which renders faster.
  • Smaller Bundle Size: AOT compilation reduces the size of the application bundle by eliminating unnecessary Angular compiler code.
  • Early Error Detection: Errors like template binding issues are caught during the build process rather than at runtime.
  • Improved Security: AOT compiles templates into JavaScript, which reduces the risk of injection attacks.

AOT is enabled by default in Angular CLI for production builds.

25. What are HTTP interceptors?

HTTP Interceptors in Angular are middleware services that intercept HTTP requests and responses. They allow you to modify requests before they are sent to the server and responses before they are passed to the application. Interceptors are useful for tasks like adding authentication tokens, logging, or handling errors globally.

Here’s an example of an HTTP interceptor that adds an authorization token to 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, next: HttpHandler): Observable> {
    const authToken = 'your-auth-token';
    const authReq = req.clone({
      headers: req.headers.set('Authorization', `Bearer ${authToken}`)
    });
    return next.handle(authReq);
  }
}
        

To use the interceptor, you need to provide it in your application module:


@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ]
})
export class AppModule {}
        

26. What is transpiling in Angular?

Transpiling in Angular (and JavaScript/TypeScript in general) refers to the process of converting code written in one programming language into another language that can be executed in a target environment. In the context of Angular, transpiling typically involves converting TypeScript code into JavaScript (ES5 or ES6) so that it can run in browsers that do not natively support TypeScript.

Angular uses the TypeScript compiler (tsc) to transpile TypeScript code into JavaScript during the build process. This allows developers to use modern TypeScript features while ensuring compatibility with all browsers.

27. What is ngOnInit?

ngOnInit is a lifecycle hook in Angular that is called after the first ngOnChanges. It is used to perform initialization tasks for a component or directive. This hook is particularly useful for fetching data, setting up subscriptions, or initializing component properties.

Here’s an example of how to use ngOnInit:


import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `<p>{{ message }}</p>`
})
export class ExampleComponent implements OnInit {
  message: string;

  ngOnInit() {
    this.message = "Component initialized!";
  }
}
        

In this example, the ngOnInit method sets the message property when the component is initialized.

28. What does Angular Material mean?

Angular Material is a UI component library developed by the Angular team. It provides a collection of reusable, well-designed, and accessible UI components that follow Google’s Material Design guidelines. Angular Material includes components like buttons, cards, dialogs, and navigation menus, which can be easily integrated into Angular applications to create a consistent and modern user interface.

Angular Material also includes features like theming, animations, and responsive design, making it easier to build visually appealing and functional applications.

29. What exactly is the router state?

In Angular, the router state represents the current state of the router, including information about the active route, route parameters, query parameters, and the URL. The router state is managed by the Router service and can be accessed to determine the current navigation context.

The router state is useful for:

  • Accessing route parameters (e.g., id in /users/:id).
  • Handling query parameters (e.g., ?search=term).
  • Navigating programmatically within the application.

You can access the router state using the Router or ActivatedRoute services.

Router links in Angular are directives used to create navigation links between different routes in a Single Page Application (SPA). The routerLink directive is used to specify the route to navigate to when the link is clicked.

Here’s an example of how to use routerLink:


<a routerLink="/home">Home</a>
<a routerLink="/about">About</a>
        

In this example, clicking the “Home” link navigates to the /home route, and clicking the “About” link navigates to the /about route. The routerLink directive is part of the RouterModule and is essential for creating navigation in Angular applications.

31. What are lifecycle hooks in Angular? Explain a few lifecycle hooks.

Lifecycle hooks in Angular are special methods that allow you to tap into key moments in the lifecycle of a component or directive—from creation to destruction. These hooks provide opportunities to perform actions at specific stages, such as initialization, change detection, and cleanup.

Here are a few commonly used lifecycle hooks:

  • ngOnChanges: Called when an input or output binding value changes. It receives a SimpleChanges object containing the current and previous values.
  • ngOnInit: Called once after the first ngOnChanges. It is used for initialization tasks, such as fetching data.
  • ngDoCheck: Called during every change detection cycle. It allows you to implement custom change detection logic.
  • ngAfterViewInit: Called after a component’s view has been fully initialized. It is useful for interacting with DOM elements.
  • ngOnDestroy: Called just before a component or directive is destroyed. It is used for cleanup tasks, such as unsubscribing from observables.

Lifecycle hooks help manage resources, optimize performance, and ensure components behave as expected throughout their lifecycle.

32. What is the Component Decorator in Angular?

The @Component decorator in Angular is used to define a class as an Angular component. It provides metadata that tells Angular how to create, render, and manage the component. The decorator includes properties such as:

  • selector: A CSS selector that identifies the component in templates.
  • template or templateUrl: Defines the HTML template for the component.
  • styleUrls: Specifies the stylesheets for the component.
  • providers: Configures dependency injection for the component.

Here’s an example of a component decorator:


import { Component } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<h1>Hello, Angular!</h1>',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent {}
        

33. What are property decorators?

Property decorators in Angular are used to modify or enhance the behavior of class properties. They are applied to properties within a class and are commonly used for data binding and dependency injection.

Common property decorators include:

  • @Input: Allows a property to receive data from a parent component.
  • @Output: Allows a property to emit events to a parent component.
  • @ViewChild and @ViewChildren: Used to get references to child components or directives.

Here’s an example of using @Input:


import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: '<p>{{ message }}</p>'
})
export class ChildComponent {
  @Input() message: string;
}
        

34. What are Method decorators?

Method decorators in Angular and TypeScript are used to modify or extend the behavior of methods in a class. While Angular itself does not provide many built-in method decorators, TypeScript and other libraries use them for various purposes, such as logging, validation, or modifying method behavior.

A common example of a method decorator in TypeScript is the @Log decorator, which can log method calls and their arguments. Here’s a conceptual example:


function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with arguments: ${JSON.stringify(args)}`);
    return originalMethod.apply(this, args);
  };
  return descriptor;
}

class Example {
  @Log
  greet(name: string) {
    return `Hello, ${name}!`;
  }
}

const example = new Example();
example.greet("Angular"); // Logs: Calling greet with arguments: ["Angular"]
        

35. What are class decorators?

Class decorators in Angular and TypeScript are used to modify or enhance the behavior of a class. They are applied to the class itself and are commonly used to define metadata or configure how the class should be processed.

In Angular, class decorators include:

  • @Component: Defines a class as an Angular component.
  • @Directive: Defines a class as an Angular directive.
  • @Injectable: Marks a class as a service that can be injected into other components or services.
  • @NgModule: Defines a class as an Angular module.

Here’s an example of a class decorator:


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {}
        

36. What exactly is a parameterized pipe?

A parameterized pipe in Angular is a custom pipe that accepts additional parameters to modify its behavior. These parameters allow you to customize the output of the pipe dynamically.

For example, you can create a pipe that formats a string based on a specified parameter. Here’s how you can define and use a parameterized pipe:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'formatText' })
export class FormatTextPipe implements PipeTransform {
  transform(value: string, format: string): string {
    if (format === 'uppercase') {
      return value.toUpperCase();
    } else if (format === 'lowercase') {
      return value.toLowerCase();
    }
    return value;
  }
}
        

You can use this pipe in a template like this:


<p>{{ 'Hello' | formatText:'uppercase' }}</p>
        

37. What are pipes in Angular? Explain with an example.

Pipes in Angular are used to transform data before it is displayed in the view. They allow you to format, filter, or modify data directly within templates. Angular provides built-in pipes like DatePipe, UpperCasePipe, and CurrencyPipe, and you can also create custom pipes.

Here’s an example of using a built-in pipe:


<p>{{ 'hello' | uppercase }}</p> 
        

You can also create a custom pipe. For example, a pipe to reverse a string:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
  transform(value: string): string {
    return value.split('').reverse().join('');
  }
}
        

Use the custom pipe in a template:


<p>{{ 'hello' | reverse }}</p> 
        

38. Explain the concept of Dependency Injection.

Dependency Injection (DI) is a design pattern and a core feature of Angular that allows components and services to delegate the responsibility of creating their dependencies to an external entity, called an injector. This promotes modularity, reusability, and testability.

In Angular, DI works as follows:

  • Providers: Classes or values that can be injected are registered as providers in the Angular injector.
  • Injectors: Angular creates injectors at different levels (e.g., root, module, or component) to manage the creation and delivery of dependencies.
  • Injection: When a component or service requests a dependency, the injector provides an instance of that dependency.

Here’s an example of using DI in Angular:


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  getData() {
    return "Data from service";
  }
}
        

import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-example',
  template: '<p>{{ data }}</p>'
})
export class ExampleComponent {
  data: string;

  constructor(private dataService: DataService) {
    this.data = this.dataService.getData();
  }
}
        

39. How are observables different from promises?

Observables and Promises are both used for asynchronous programming in JavaScript, but they have key differences:

  • Observables:
    • Represent a stream of values over time.
    • Can emit multiple values (e.g., events, data from WebSockets).
    • Support operators like map, filter, and merge for transforming data.
    • Are lazy, meaning they only execute when subscribed to.
    • Can be canceled using the unsubscribe method.
  • Promises:
    • Represent a single future value or error.
    • Can only resolve or reject once.
    • Do not support operators for transforming data.
    • Are eager, meaning they execute immediately when created.
    • Cannot be canceled.

Observables are part of the RxJS library and are widely used in Angular for handling asynchronous operations, such as HTTP requests and user events.

40. Explain string interpolation and property binding in Angular.

String interpolation and property binding are two ways to bind data from a component to a view in Angular.

  • String Interpolation: Uses double curly braces {{ }} to display component properties in the template. It is a one-way binding from the component to the view.
    
    <p>Hello, {{ userName }}!</p>
                    
  • Property Binding: Uses square brackets [] to bind a component property to an element property. It is also a one-way binding but allows you to set properties of DOM elements.
    
    <img [src]="imageUrl" alt="Image">
                    

Both techniques are essential for creating dynamic and interactive user interfaces in Angular applications.

41. What are RxJs in Angular?

RxJS (Reactive Extensions for JavaScript) is a library for reactive programming that uses Observables to handle asynchronous data streams. In Angular, RxJS is extensively used for managing asynchronous operations such as HTTP requests, user inputs, and other event-based interactions.

RxJS provides powerful features like:

  • Observables: Represent a stream of data that can be observed over time.
  • Operators: Allow you to manipulate, filter, and transform data streams (e.g., map, filter, merge).
  • Subjects: Act as both an Observable and an Observer, allowing multicasting of data to multiple subscribers.
  • Schedulers: Control the execution context of Observables, enabling concurrency and asynchronous operations.

RxJS is integral to Angular’s HttpClient module, forms, and event handling, making it easier to manage complex asynchronous workflows.

42. What is view encapsulation in Angular?

View encapsulation in Angular determines how styles defined in a component are applied to its template and whether they affect other components. Angular provides three view encapsulation strategies:

  • ViewEncapsulation.Emulated (default): Angular emulates shadow DOM behavior by adding unique attributes to component elements and scoping styles to those attributes.
  • ViewEncapsulation.Native: Uses the browser’s native shadow DOM to encapsulate styles. This is not widely supported across all browsers.
  • ViewEncapsulation.None: Styles are globally applied without any encapsulation, affecting all elements on the page.

You can set the encapsulation strategy in the component decorator:


import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css'],
  encapsulation: ViewEncapsulation.Emulated
})
export class ExampleComponent {}
        

43. What is Eager and Lazy loading?

Eager loading and lazy loading are two strategies for loading modules in Angular applications:

  • Eager Loading: All modules are loaded when the application starts. This is the default behavior and is suitable for small applications or modules that are always required.
    
    @NgModule({
      imports: [BrowserModule, AppModule]
    })
    export class AppModule {}
                    
  • Lazy Loading: Modules are loaded on-demand when they are needed, improving the initial load time of the application. This is ideal for large applications with many features.
    
    const routes: Routes = [
      { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
    ];
                    

Lazy loading is configured using the loadChildren property in the router configuration.

44. Can one make an Angular application to render on the server-side?

Yes, you can make an Angular application render on the server-side using Angular Universal. Angular Universal is a technology that enables server-side rendering (SSR) of Angular applications, improving performance, SEO, and user experience.

SSR generates the HTML of your application on the server, sending a fully rendered page to the client. This is particularly useful for:

  • Improving SEO, as search engines can crawl fully rendered pages.
  • Faster initial load times, especially on slow networks.
  • Better user experience, as users see content immediately while the client-side application loads.

To use Angular Universal, you need to set up a server-side rendering engine, such as Node.js, and configure your Angular application to support SSR.

45. What happens when you use the script tag within a template?

When you use a <script> tag within an Angular template, Angular sanitizes and removes it by default. This is a security measure to prevent Cross-Site Scripting (XSS) attacks. Angular does not execute or render script tags in templates to protect against malicious code injection.

If you need to dynamically load scripts, you should use Angular’s DomSanitizer or other safe methods to add scripts to the DOM programmatically.

46. How can I include SASS into an Angular project?

To include SASS (Syntactically Awesome Style Sheets) in an Angular project, follow these steps:

  1. Install SASS globally or as a dev dependency in your project:
    
    npm install -g sass
    # or
    npm install sass --save-dev
                    
  2. Update the angular.json file to use SASS for styles. Change the styles extension from css to scss:
    
    "schematics": {
      "@schematics/angular:component": {
        "style": "scss"
      }
    }
                    
  3. Rename your style files from *.css to *.scss and update any imports accordingly.

Once configured, you can use SASS features like variables, nesting, and mixins in your Angular project.

47. How do you deal with errors in observables?

In RxJS, you can handle errors in Observables using several operators:

  • catchError: Catches errors and allows you to return a fallback Observable or throw a new error.
    
    import { catchError } from 'rxjs/operators';
    import { of } from 'rxjs';
    
    observable.pipe(
      catchError(error => {
        console.error('Error:', error);
        return of('Fallback value');
      })
    );
                    
  • retry: Automatically resubscribes to the Observable a specified number of times if it errors.
    
    import { retry } from 'rxjs/operators';
    
    observable.pipe(retry(3));
                    
  • finalize: Executes a callback when the Observable completes or errors, useful for cleanup tasks.
    
    import { finalize } from 'rxjs/operators';
    
    observable.pipe(
      finalize(() => console.log('Observable completed or errored'))
    );
                    

These operators help manage errors gracefully and ensure your application remains robust.

48. How does one share data between components in Angular?

In Angular, you can share data between components using several methods:

  • Parent to Child: Use @Input to pass data from a parent component to a child component.
    
    // Parent Component
    <app-child [childData]="parentData"></app-child>
    
    // Child Component
    @Input() childData: any;
                    
  • Child to Parent: Use @Output and EventEmitter to emit events from a child component to a parent component.
    
    // Child Component
    @Output() dataEvent = new EventEmitter<any>();
    this.dataEvent.emit(data);
    
    // Parent Component
    <app-child (dataEvent)="handleData($event)"></app-child>
                    
  • Shared Service: Use a shared service with RxJS Subject or BehaviorSubject to share data between unrelated components.
    
    // Shared Service
    @Injectable({ providedIn: 'root' })
    export class DataService {
      private dataSubject = new BehaviorSubject<any>(null);
      data$ = this.dataSubject.asObservable();
    
      updateData(data: any) {
        this.dataSubject.next(data);
      }
    }
    
    // Component 1
    this.dataService.updateData(newData);
    
    // Component 2
    this.dataService.data$.subscribe(data => console.log(data));
                    

49. How do you choose an element from a component template?

To select or reference an element from a component template in Angular, you can use:

  • Template Reference Variables: Use a hash symbol (#) to create a reference to an element in the template.
    
    <input #myInput type="text">
    <button (click)="logInput(myInput.value)">Log Input</button>
                    
  • @ViewChild and @ViewChildren: Use these decorators to get references to elements, components, or directives in the component class.
    
    import { ViewChild, ElementRef } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: '<input #myInput type="text">'
    })
    export class ExampleComponent {
      @ViewChild('myInput') inputElement: ElementRef;
    
      ngAfterViewInit() {
        this.inputElement.nativeElement.focus();
      }
    }
                    

50. In AngularJS, a module is created using which of the following syntax?

In AngularJS, a module is created using the angular.module method. Here is the syntax:


var app = angular.module('myApp', []);
        

In this example, 'myApp' is the name of the module, and the empty array [] is used to specify dependencies. If the module does not exist, AngularJS creates it; otherwise, it retrieves the existing module.

61. What is Form Builder?

FormBuilder in Angular is a service that simplifies the process of creating and managing reactive forms. It provides a convenient, fluent API to define form controls, form groups, and form arrays with minimal boilerplate code. FormBuilder is part of the @angular/forms module.

Here’s an example of how to use FormBuilder to create a reactive form:


import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-example',
  template: `
    <form [formGroup]="myForm">
      <input formControlName="name" placeholder="Name">
      <input formControlName="email" placeholder="Email">
    </form>
  `
})
export class ExampleComponent {
  myForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      name: [''],
      email: ['']
    });
  }
}
        

FormBuilder helps reduce the complexity of creating forms, especially when dealing with nested form groups or arrays.

62. What is the purpose of the @Output decorator?

The @Output decorator in Angular is used to create custom events that allow a child component to communicate with its parent component. It works in conjunction with EventEmitter to emit events that the parent component can listen to and respond to.

Here’s an example of how to use @Output:


import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: '<button (click)="sendMessage()">Send Message</button>'
})
export class ChildComponent {
  @Output() messageEvent = new EventEmitter<string>();

  sendMessage() {
    this.messageEvent.emit("Hello from Child!");
  }
}
        

// Parent Component
@Component({
  selector: 'app-parent',
  template: '<app-child (messageEvent)="receiveMessage($event)"></app-child>'
})
export class ParentComponent {
  receiveMessage(message: string) {
    console.log(message); // Output: Hello from Child!
  }
}
        

The @Output decorator enables parent-child communication by allowing child components to emit events that parents can handle.

63. Which architectures does Angular use?

Angular primarily uses the following architectural patterns:

  • Component-Based Architecture: Angular applications are built using components, which are self-contained units of UI and logic. Components are the building blocks of Angular applications.
  • MVVM (Model-View-ViewModel): Angular follows the MVVM pattern, where the Model represents the data, the View represents the UI, and the ViewModel (component class) acts as the intermediary between the Model and the View.
  • Modular Architecture: Angular applications are organized into modules, which group related components, directives, pipes, and services. This promotes reusability and maintainability.
  • Dependency Injection: Angular uses a hierarchical dependency injection system to manage and provide dependencies to components and services.

These architectures help Angular applications remain scalable, maintainable, and efficient.

64. Which of the following is true about $routeProvider?

The $routeProvider is a service used in AngularJS (Angular 1.x) to configure routes for Single Page Applications (SPAs). Here are some key points about $routeProvider:

  • It is used to define routes and map them to controllers and templates.
  • It allows you to specify route parameters and resolve dependencies before a route is activated.
  • It is part of the ngRoute module, which must be included as a dependency in your AngularJS application.

Example of using $routeProvider:


angular.module('myApp', ['ngRoute'])
  .config(function($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'home.html',
        controller: 'HomeController'
      })
      .when('/about', {
        templateUrl: 'about.html',
        controller: 'AboutController'
      })
      .otherwise({
        redirectTo: '/'
      });
  });
        

65. Which prefix is used with the AngularJS directives?

In AngularJS, directives are typically prefixed with ng-. This prefix helps distinguish AngularJS directives from standard HTML attributes and elements.

Examples of AngularJS directives with the ng- prefix:

  • ng-app: Defines the root element of an AngularJS application.
  • ng-model: Binds the value of HTML controls to application data.
  • ng-repeat: Repeats HTML elements for each item in a collection.
  • ng-if: Conditionally includes or excludes HTML elements based on an expression.

66. Which type of binding uses the banana box [()]?

The banana box syntax [()] in Angular is used for two-way data binding. It combines property binding ([]) and event binding (()) to keep the model and view in sync.

The most common example of two-way data binding in Angular is using [(ngModel)]:


<input [(ngModel)]="userName" placeholder="Enter your name">
<p>Hello, {{ userName }}!</p>
        

In this example, any changes to the input field automatically update the userName property in the component, and vice versa.

67. What is Angular, and how is it different from AngularJS?

Angular is a modern, open-source framework for building dynamic web applications, developed and maintained by Google. It is a complete rewrite of AngularJS (Angular 1.x) and introduces significant improvements in performance, architecture, and features.

Here are the key differences between Angular and AngularJS:

  • Language: Angular uses TypeScript, while AngularJS uses JavaScript.
  • Architecture: Angular follows a component-based architecture, whereas AngularJS uses a Model-View-Controller (MVC) architecture.
  • Performance: Angular is faster due to features like Ahead-of-Time (AOT) compilation and improved change detection.
  • Data Binding: Angular uses two-way data binding with [(ngModel)], while AngularJS uses ng-model.
  • Dependency Injection: Angular has a hierarchical dependency injection system, while AngularJS uses a simpler DI mechanism.
  • Mobile Support: Angular is designed with mobile support in mind, while AngularJS has limited mobile capabilities.
  • Routing: Angular uses @angular/router, while AngularJS uses ngRoute.

Angular is the recommended choice for new projects due to its modern features, better performance, and improved tooling.

68. What are the Components in Angular?

In Angular, a component is a fundamental building block that defines a part of the user interface. Components are self-contained units that consist of:

  • Template: Defines the HTML structure of the component.
  • Class: Contains the logic and data for the component.
  • Metadata: Defined using the @Component decorator, which includes properties like selector, templateUrl, and styleUrls.

Here’s an example of a simple Angular component:


import { Component } from '@angular/core';

@Component({
  selector: 'app-greeting',
  template: '<h1>Hello, {{ name }}!</h1>',
  styleUrls: ['./greeting.component.css']
})
export class GreetingComponent {
  name = 'Angular';
}
        

Components are reusable and can be nested within other components to build complex UIs.

69. What is Data Binding in Angular? What are the types of Data Binding?

Data binding in Angular is a mechanism that synchronizes data between the model (component) and the view (template). It ensures that the UI reflects the current state of the application and vice versa.

There are four types of data binding in Angular:

  • Interpolation ({{ data }}): One-way binding from the component to the view.
    
    <p>{{ message }}</p>
                    
  • Property Binding ([property]="data"): One-way binding from the component to an element property.
    
    <img [src]="imageUrl">
                    
  • Event Binding ((event)="handler()"): One-way binding from the view to the component.
    
    <button (click)="onClick()">Click Me</button>
                    
  • Two-Way Binding ([(ngModel)]="data"): Synchronizes data between the component and the view.
    
    <input [(ngModel)]="userName">
                    

Data binding simplifies the process of keeping the UI in sync with the application state, making Angular applications dynamic and responsive.

70. When we talk about Angular, what is the purpose of @NgModule?

The @NgModule decorator in Angular is used to define a module, which is a way to organize and bundle related components, directives, pipes, and services. Modules help manage the complexity of an application by grouping functionality into cohesive blocks.

The @NgModule decorator includes several key properties:

  • declarations: Specifies the components, directives, and pipes that belong to this module.
  • imports: Lists other modules whose exported components, directives, or pipes are needed by this module.
  • providers: Configures the dependency injection system by specifying services that can be injected into components.
  • bootstrap: Defines the root component that Angular creates when bootstrapping the application.

Here’s an example of an @NgModule:


import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}
        

The @NgModule decorator helps Angular understand how to compile and run the application.

61. What is Dependency Injection (DI), and why is it used in Angular?

Dependency Injection (DI) is a design pattern and a core feature of Angular that allows a class to receive its dependencies from an external source rather than creating them itself. This promotes modularity, reusability, and testability in applications.

In Angular, DI is used to:

  • Manage dependencies between components and services.
  • Inject services into components, directives, or other services.
  • Simplify the process of swapping implementations for testing or different environments.

Here’s an example of DI in Angular:


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  getData() {
    return "Data from service";
  }
}
        

import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-example',
  template: '<p>{{ data }}</p>'
})
export class ExampleComponent {
  data: string;

  constructor(private dataService: DataService) {
    this.data = this.dataService.getData();
  }
}
        

DI helps keep components lean and focused on their primary responsibilities by delegating dependency management to Angular’s injector.

62. What is Angular CLI, and what is it useful for?

The Angular CLI (Command Line Interface) is a powerful tool provided by the Angular team to streamline the development process. It automates many tasks, such as project setup, code generation, testing, and deployment.

Angular CLI is useful for:

  • Creating new Angular projects with a single command: ng new project-name.
  • Generating components, services, directives, and pipes: ng generate component component-name.
  • Running and building applications for development and production.
  • Running tests and performing linting.
  • Managing dependencies and configurations.

Angular CLI significantly speeds up development by automating repetitive tasks and enforcing best practices.

63. What are Pipes in Angular?

Pipes in Angular are used to transform data before it is displayed in the view. They allow you to format, filter, or modify data directly within templates. Angular provides built-in pipes like DatePipe, UpperCasePipe, and CurrencyPipe, and you can also create custom pipes.

Here’s an example of using a built-in pipe:


<p>{{ 'hello' | uppercase }}</p> 
        

You can also create a custom pipe. For example, a pipe to reverse a string:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
  transform(value: string): string {
    return value.split('').reverse().join('');
  }
}
        

Use the custom pipe in a template:


<p>{{ 'hello' | reverse }}</p> 
        

64. What is the difference between the constructor and ngOnInit?

The constructor and ngOnInit serve different purposes in Angular components:

  • Constructor:
    • A TypeScript feature used to initialize class members when an instance is created.
    • Called when the component is instantiated but before any Angular-specific initialization.
    • Used primarily for dependency injection.
  • ngOnInit:
    • An Angular lifecycle hook called after the first ngOnChanges.
    • Used for initialization tasks that depend on input properties being set.
    • Ideal for fetching data or setting up subscriptions.

Example:


import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<p>{{ message }}</p>'
})
export class ExampleComponent implements OnInit {
  message: string;

  constructor() {
    console.log('Constructor called');
  }

  ngOnInit() {
    this.message = "Component initialized!";
    console.log('ngOnInit called');
  }
}
        

65. What is the role of ngFor and ngIf in Angular?

*ngFor and *ngIf are structural directives in Angular used to manipulate the DOM dynamically:

  • *ngFor:
    • Used to iterate over a collection (e.g., an array) and render a template for each item.
    • Example:
      
      <ul>
        <li *ngFor="let item of items">{{ item }}</li>
      </ul>
                              
  • *ngIf:
    • Used to conditionally include or exclude a portion of the template based on a boolean expression.
    • Example:
      
      <p *ngIf="isVisible">This text is visible!</p>
                              

Both directives help create dynamic and responsive user interfaces by controlling what is rendered based on application state.

66. What do you know about metadata in Angular?

In Angular, metadata is used to provide additional information about classes, such as components, directives, and modules. Metadata is defined using decorators like @Component, @Directive, and @NgModule. It tells Angular how to process and use these classes.

For example, the @Component decorator includes metadata such as:

  • selector: The CSS selector for the component.
  • template or templateUrl: The HTML template for the component.
  • styleUrls: The stylesheets for the component.
  • providers: Services available for dependency injection.

Example:


@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent {}
        

67. What are Angular Services? How do they differ from components?

Services in Angular are singleton objects that provide specific functionality to components and other services. They are used to encapsulate business logic, data access, and other reusable functions. Services are typically injected into components via dependency injection.

Key differences between services and components:

  • Purpose:
    • Services handle business logic, data access, and reusable functionality.
    • Components manage the view and user interactions.
  • Lifecycle:
    • Services are singletons by default and persist throughout the application lifecycle.
    • Components are instantiated and destroyed as users navigate through the application.
  • Usage:
    • Services are injected into components or other services.
    • Components are used to define parts of the user interface.

Example of a service:


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  getData() {
    return "Data from service";
  }
}
        

68. What are Angular lifecycle hooks? What are they used for?

Lifecycle hooks in Angular are special methods that allow you to tap into key moments in the lifecycle of a component or directive—from creation to destruction. They provide opportunities to perform actions at specific stages, such as initialization, change detection, and cleanup.

Common lifecycle hooks include:

  • ngOnChanges: Called when an input or output binding value changes.
  • ngOnInit: Called after the first ngOnChanges. Used for initialization tasks.
  • ngDoCheck: Called during every change detection cycle. Used for custom change detection.
  • ngAfterViewInit: Called after a component’s view has been fully initialized.
  • ngOnDestroy: Called just before a component or directive is destroyed. Used for cleanup tasks.

Example of using lifecycle hooks:


import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<p>Example Component</p>'
})
export class ExampleComponent implements OnInit, OnDestroy {
  ngOnInit() {
    console.log('Component initialized');
  }

  ngOnDestroy() {
    console.log('Component destroyed');
  }
}
        

69. What do we mean by Change Detection in Angular? How does it work?

Change Detection in Angular is the mechanism by which the framework detects changes in the application’s data and updates the DOM accordingly. It ensures that the view is always synchronized with the model.

Angular uses a Change Detection Mechanism based on zones. Here’s how it works:

  1. Zone.js: Angular uses Zone.js to detect asynchronous operations (like user events, timers, or HTTP requests) that might change the application state.
  2. Change Detection Cycle: When an asynchronous event occurs, Zone.js triggers Angular’s change detection cycle. During this cycle, Angular checks all components to see if their data has changed.
  3. Update the View: If a change is detected, Angular updates the affected parts of the DOM to reflect the new state.

Angular provides two strategies for change detection:

  • Default Strategy: Checks all components for changes.
  • OnPush Strategy: Only checks components when their input properties change or when an event is triggered within the component.

70. What are the differences between template-driven Forms and Reactive Forms?

Angular provides two approaches to handling forms: Template-Driven Forms and Reactive Forms. Here are the key differences:

  • Template-Driven Forms:
    • Forms are defined in the template using directives like ngModel.
    • Two-way data binding is used to sync the model and view.
    • Suitable for simple forms with minimal validation.
    • Less control over form validation and state.
    
    <form>
      <input [(ngModel)]="user.name" name="name">
    </form>
                    
  • Reactive Forms:
    • Forms are defined programmatically in the component class.
    • Provides explicit control over form validation and state.
    • Suitable for complex forms with dynamic controls and advanced validation.
    • Uses FormGroup, FormControl, and FormBuilder.
    
    this.form = this.fb.group({
      name: ['', Validators.required]
    });
                    
    
    <form [formGroup]="form">
      <input formControlName="name">
    </form>
                    

Reactive Forms offer more control and flexibility, making them ideal for complex scenarios, while Template-Driven Forms are simpler and quicker to set up for basic use cases.

71. What are Observables in Angular, and how do you use them?

Observables in Angular are part of the RxJS library and are used to handle asynchronous data streams. They represent a sequence of values that can be observed over time, allowing you to react to changes or events such as user inputs, HTTP responses, or timers.

Observables are powerful because they can emit multiple values over time, unlike Promises, which resolve only once. They also support operators like map, filter, and merge to transform and manage data streams.

Here’s an example of how to use Observables in Angular:


import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';

@Component({
  selector: 'app-example',
  template: '<p>{{ message }}</p>'
})
export class ExampleComponent {
  message: string = '';

  constructor() {
    const dataObservable: Observable<string> = of('Hello', 'World');

    dataObservable.pipe(
      map(value => value.toUpperCase())
    ).subscribe(value => {
      this.message += value + ' ';
    });
  }
}
        

In this example, the Observable emits two values, which are transformed to uppercase and then subscribed to update the component’s message property.

72. What is Angular Routing and lazy loading, with an example?

Angular Routing enables navigation between different views or components in a Single Page Application (SPA) without reloading the page. Lazy loading is a technique to load feature modules on-demand, improving the initial load time of the application.

Here’s an example of setting up Angular Routing with lazy loading:


// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}
        

In this example, the LazyModule is loaded only when the user navigates to the /lazy route.

73. What are Angular Guards, and how do they protect routes?

Angular Guards are interfaces that allow you to control navigation to and from routes based on certain conditions. They are used to protect routes by implementing logic such as authentication checks, unsaved changes warnings, or role-based access control.

Common types of guards include:

  • CanActivate: Determines if a route can be activated.
  • CanDeactivate: Determines if a route can be deactivated.
  • CanLoad: Determines if a lazy-loaded module can be loaded.

Here’s an example of a CanActivate guard:


import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(): boolean {
    if (this.isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }

  private isLoggedIn(): boolean {
    // Add your authentication logic here
    return !!localStorage.getItem('token');
  }
}
        

To use the guard, add it to your route configuration:


const routes: Routes = [
  { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }
];
        

74. How do you create and use custom Pipes?

Custom Pipes in Angular allow you to define your own transformations for data displayed in templates. You can create a custom pipe by implementing the PipeTransform interface.

Here’s an example of creating and using a custom pipe:


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
  transform(value: string): string {
    return value.split('').reverse().join('');
  }
}
        

To use the custom pipe in a template:


<p>{{ 'hello' | reverse }}</p> 
        

Custom pipes are useful for transforming data in ways that are specific to your application’s needs.

75. What is the purpose of Angular’s Renderer2?

Renderer2 in Angular is a service that provides an abstraction layer for manipulating the DOM in a platform-agnostic way. It allows you to create, update, and remove elements without directly accessing the DOM, which is especially useful for server-side rendering and web workers.

Renderer2 is part of Angular’s effort to improve security and compatibility across different platforms. It helps prevent direct DOM manipulation, which can lead to security vulnerabilities like XSS attacks.

Here’s an example of using Renderer2:


import { Component, Renderer2, OnInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<div #myDiv>Hello</div>'
})
export class ExampleComponent implements OnInit {
  constructor(private renderer: Renderer2) {}

  ngOnInit() {
    const div = this.renderer.createElement('div');
    const text = this.renderer.createText('World');
    this.renderer.appendChild(div, text);
    this.renderer.appendChild(document.body, div);
  }
}
        

76. What is the difference between Observable and Promise?

Observables and Promises are both used for asynchronous programming in JavaScript, but they have key differences:

  • Observables:
    • Can emit multiple values over time.
    • Support operators like map, filter, and merge.
    • Are lazy; they only execute when subscribed to.
    • Can be canceled using the unsubscribe method.
  • Promises:
    • Resolve or reject only once.
    • Do not support operators for transforming data.
    • Are eager; they execute immediately when created.
    • Cannot be canceled.

Observables are more powerful and flexible for handling complex asynchronous operations, while Promises are simpler and suitable for one-time asynchronous tasks.

77. How can you implement conditional rendering in an Angular template?

Conditional rendering in Angular templates can be implemented using structural directives like *ngIf, *ngSwitch, and *ngIf.

Here’s an example of conditional rendering with *ngIf:


<div *ngIf="isLoggedIn">
  <p>Welcome back!</p>
</div>
<div *ngIf="!isLoggedIn">
  <p>Please log in.</p>
</div>
        

You can also use *ngSwitch for multiple conditions:


<div [ngSwitch]="status">
  <p *ngSwitchCase="'active'">Active</p>
  <p *ngSwitchCase="'inactive'">Inactive</p>
  <p *ngSwitchDefault>Unknown</p>
</div>
        

78. What are Angular modules? Give examples.

Angular modules are containers that group related components, directives, pipes, and services. They help organize an application into cohesive blocks of functionality. Every Angular application has at least one module, the root module, named AppModule.

Modules are defined using the @NgModule decorator, which includes metadata such as:

  • declarations: Components, directives, and pipes that belong to this module.
  • imports: Other modules whose exported classes are needed by this module.
  • providers: Services available for dependency injection.
  • bootstrap: The root component that Angular creates when bootstrapping the application.

Here’s an example of an Angular module:


import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}
        

Modules help manage dependencies and ensure that only the necessary code is loaded, improving performance and maintainability.

79. What is Ahead-of-Time (AOT) Compilation in Angular, and why is it important?

Ahead-of-Time (AOT) Compilation in Angular is the process of compiling Angular applications during the build phase, before they are deployed to the browser. This is in contrast to Just-in-Time (JIT) compilation, where the application is compiled in the browser at runtime.

Advantages of AOT:

  • Faster Rendering: The browser downloads a pre-compiled version of the application, which renders faster.
  • Smaller Bundle Size: AOT compilation reduces the size of the application bundle by eliminating unnecessary Angular compiler code.
  • Early Error Detection: Errors like template binding issues are caught during the build process rather than at runtime.
  • Improved Security: AOT compiles templates into JavaScript, which reduces the risk of injection attacks.

AOT is enabled by default in Angular CLI for production builds.

80. What is Angular Universal, and how does it enable server-side rendering?

Angular Universal is a technology that enables server-side rendering (SSR) of Angular applications. SSR generates the HTML of your application on the server, sending a fully rendered page to the client. This improves performance, SEO, and user experience.

Benefits of Angular Universal:

  • Improved SEO: Search engines can crawl fully rendered pages.
  • Faster Initial Load: Users see content immediately while the client-side application loads.
  • Better User Experience: Reduces the perceived load time, especially on slow networks.

To use Angular Universal, you need to set up a server-side rendering engine, such as Node.js, and configure your Angular application to support SSR. Angular Universal provides tools and libraries to simplify this process.

81. How do you optimize Angular Change Detection in large applications?

Optimizing Change Detection in large Angular applications is crucial for maintaining performance. Here are some strategies to achieve this:

  • Use OnPush Change Detection Strategy: By setting the changeDetection: ChangeDetectionStrategy.OnPush in your component, Angular will only check the component when its input properties change or when an event is triggered within the component.
    
    import { Component, ChangeDetectionStrategy } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class ExampleComponent {}
                    
  • Avoid Complex Computations in Templates: Move heavy computations to component methods or use pure pipes to cache results.
  • Use Immutable Data: Immutable data structures ensure that changes are detected efficiently, especially with the OnPush strategy.
  • Detach Change Detectors: For components that don’t need frequent updates, you can detach their change detectors using ChangeDetectorRef.detach() and manually trigger updates when needed.
  • Optimize Observables: Use operators like debounceTime, distinctUntilChanged, and shareReplay to minimize unnecessary emissions and computations.

82. What is the difference between a Pure and Impure Pipe in Angular?

In Angular, Pipes can be categorized as either Pure or Impure based on their behavior:

  • Pure Pipes:
    • Are stateless and produce the same output for the same input.
    • Are only executed when Angular detects a change in the input values.
    • Are optimized for performance as they are not recalculated unnecessarily.
    
    @Pipe({ name: 'purePipe' })
    export class PurePipe implements PipeTransform {
      transform(value: any): any {
        return value;
      }
    }
                    
  • Impure Pipes:
    • Can have internal state and may produce different outputs for the same input.
    • Are executed during every change detection cycle, regardless of input changes.
    • Can impact performance if overused, as they are recalculated frequently.
    
    @Pipe({
      name: 'impurePipe',
      pure: false
    })
    export class ImpurePipe implements PipeTransform {
      transform(value: any): any {
        return value;
      }
    }
                    

83. What is the purpose of the Zone.js library in Angular?

Zone.js is a library used by Angular to handle asynchronous operations. It provides a mechanism called “Zones” that allows Angular to detect when asynchronous tasks (such as user events, timers, or HTTP requests) occur and trigger change detection accordingly.

Key purposes of Zone.js in Angular:

  • Monitors asynchronous operations to determine when to run change detection.
  • Ensures that Angular’s change detection mechanism is aware of changes that occur outside the Angular context.
  • Simplifies the process of managing asynchronous tasks by providing a consistent way to patch and track them.

84. Describe Angular’s HTTP interceptors and use cases.

HTTP Interceptors in Angular are middleware services that intercept HTTP requests and responses. They allow you to modify requests before they are sent to the server and responses before they are passed to the application. Interceptors are useful for tasks like adding authentication tokens, logging, or handling errors globally.

Here’s an example of an HTTP interceptor that adds an authorization token to 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, next: HttpHandler): Observable> {
    const authToken = 'your-auth-token';
    const authReq = req.clone({
      headers: req.headers.set('Authorization', `Bearer ${authToken}`)
    });
    return next.handle(authReq);
  }
}
        

To use the interceptor, you need to provide it in your application module:


@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ]
})
export class AppModule {}
        

Use cases for HTTP interceptors include:

  • Adding authentication tokens to requests.
  • Logging HTTP requests and responses.
  • Handling errors globally.
  • Modifying request or response headers.

85. How do you secure Angular applications?

Securing Angular applications involves implementing various best practices and techniques to protect against common vulnerabilities. Here are some key strategies:

  • Authentication and Authorization: Use authentication mechanisms like OAuth2 or JWT to secure API endpoints and ensure only authorized users can access certain features.
  • Input Validation: Validate all user inputs on both the client and server sides to prevent injection attacks.
  • Sanitization: Use Angular’s built-in sanitization to prevent Cross-Site Scripting (XSS) attacks. Avoid using innerHTML directly; instead, use DomSanitizer.
  • HTTPS: Ensure all communications between the client and server are encrypted using HTTPS.
  • Content Security Policy (CSP): Implement CSP headers to mitigate XSS risks by restricting sources of executable scripts.
  • Secure Dependencies: Regularly update dependencies to patch known vulnerabilities and use tools like npm audit to identify security issues.
  • Server-Side Rendering (SSR): Use Angular Universal to render pages on the server, improving security and SEO.

86. What are Angular Elements?

Angular Elements is a feature in Angular that allows you to package Angular components as custom elements (Web Components). This enables you to use Angular components in non-Angular environments, such as vanilla JavaScript applications or other frameworks.

Key points about Angular Elements:

  • Custom elements created with Angular Elements can be used anywhere HTML is supported.
  • They provide a way to leverage Angular’s powerful features in a micro-frontend architecture.
  • Angular Elements use the createCustomElement function from @angular/elements to convert Angular components into custom elements.

Example of creating an Angular Element:


import { createCustomElement } from '@angular/elements';
import { AppComponent } from './app.component';
import { NgModule, Injector } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

@NgModule({
  imports: [BrowserModule],
  entryComponents: [AppComponent]
})
export class AppModule {
  constructor(private injector: Injector) {}

  ngDoBootstrap() {
    const customElement = createCustomElement(AppComponent, { injector: this.injector });
    customElements.define('my-custom-element', customElement);
  }
}
        

87. How do you ensure memory leaks are handled in Angular applications?

Handling memory leaks in Angular applications is essential for maintaining performance and stability. Here are some strategies to prevent memory leaks:

  • Unsubscribe from Observables: Always unsubscribe from Observables in components to prevent memory leaks, especially in ngOnDestroy.
    
    import { OnDestroy } from '@angular/core';
    import { Subscription } from 'rxjs';
    
    export class ExampleComponent implements OnDestroy {
      private subscription: Subscription;
    
      constructor(private dataService: DataService) {
        this.subscription = this.dataService.getData().subscribe(data => {
          // Handle data
        });
      }
    
      ngOnDestroy() {
        this.subscription.unsubscribe();
      }
    }
                    
  • Avoid Circular References: Ensure that objects do not hold circular references that prevent garbage collection.
  • Use Weak References: Consider using WeakMap or WeakSet for caching to allow garbage collection.
  • Detach Event Listeners: Remove event listeners when they are no longer needed.
  • Use Angular’s Built-in Tools: Utilize Angular’s change detection and dependency injection to manage object lifecycles effectively.

88. What would be your method for creating a custom structural directive in Angular?

To create a custom structural directive in Angular, you need to define a directive that modifies the DOM by adding or removing elements. Structural directives are identified by the asterisk (*) prefix in templates.

Here’s an example of creating a custom structural directive named *appIf:


import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({ selector: '[appIf]' })
export class AppIfDirective {
  constructor(
    private templateRef: TemplateRef,
    private viewContainer: ViewContainerRef
  ) {}

  @Input() set appIf(condition: boolean) {
    if (condition) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      this.viewContainer.clear();
    }
  }
}
        

You can use this directive in a template as follows:


<div *appIf="isVisible">This content is conditionally visible.</div>
        

In this example, the *appIf directive adds or removes the <div> element based on the isVisible condition.

89. If you do not supply a handler for the observer, what will happen?

In RxJS, if you do not supply a handler for an Observer, the following behaviors occur:

  • Next Handler: If you don’t provide a next handler, the Observer will ignore any values emitted by the Observable.
  • Error Handler: If you don’t provide an error handler, any errors emitted by the Observable will be thrown as uncaught exceptions, potentially crashing your application.
  • Complete Handler: If you don’t provide a complete handler, the Observer will simply ignore the completion notification from the Observable.

Example of an Observer without handlers:


import { Observable } from 'rxjs';

const observable = new Observable(subscriber => {
  subscriber.next('Value');
  subscriber.error('Error');
  subscriber.complete();
});

// No handlers provided
observable.subscribe();
        

In this case, the emitted values and completion are ignored, but the error will be thrown as an uncaught exception.

90. What is RxJS in Angular?

RxJS (Reactive Extensions for JavaScript) is a library for reactive programming that uses Observables to handle asynchronous data streams. In Angular, RxJS is extensively used for managing asynchronous operations such as HTTP requests, user inputs, and other event-based interactions.

Key features of RxJS in Angular:

  • Observables: Represent a stream of data that can be observed over time. They can emit multiple values and support operations like map, filter, and merge.
  • Operators: Allow you to transform, filter, and combine data streams. Examples include debounceTime, distinctUntilChanged, and switchMap.
  • Subjects: Act as both an Observable and an Observer, allowing multicasting of data to multiple subscribers.
  • Schedulers: Control the execution context of Observables, enabling concurrency and asynchronous operations.

RxJS is integral to Angular’s HttpClient module, forms, and event handling, making it easier to manage complex asynchronous workflows.

Example of using RxJS in Angular:


import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';

const data$: Observable = of('Hello', 'World');

data$.pipe(
  map(value => value.toUpperCase())
).subscribe(value => {
  console.log(value); // Output: HELLO, WORLD
});
        

91. What does it mean to be a senior developer?

Being a senior developer goes beyond technical expertise. It encompasses a combination of skills, experience, and mindset that contribute to the success of projects and teams. Here’s what it typically means:

  • Technical Mastery: A deep understanding of programming languages, frameworks, and tools relevant to the domain. For Angular, this includes proficiency in TypeScript, RxJS, and Angular’s core concepts.
  • Problem-Solving: The ability to analyze complex problems, design effective solutions, and anticipate potential challenges.
  • Architectural Design: Experience in designing scalable, maintainable, and efficient systems. This includes making decisions about state management, modularization, and performance optimization.
  • Mentorship: Guiding and mentoring junior developers, sharing knowledge, and fostering a collaborative team environment.
  • Code Quality: Writing clean, well-documented, and testable code. Emphasizing best practices like SOLID principles, design patterns, and code reviews.
  • Communication: Effectively communicating with stakeholders, product managers, and other team members to align technical solutions with business goals.
  • Adaptability: Staying updated with industry trends, adopting new technologies, and adapting to changing project requirements.
  • Ownership: Taking responsibility for the success of projects, ensuring timely delivery, and maintaining high standards of quality.

A senior developer is not just a coder but a leader who drives technical excellence and contributes to the growth of the team and organization.

92. Do you prefer declarative or imperative programming?

The choice between declarative and imperative programming depends on the context and the problem being solved:

  • Declarative Programming:
    • Focuses on what needs to be done rather than how to do it.
    • Examples include SQL, HTML, and Angular templates.
    • Benefits: Easier to read, maintain, and reason about. Encourages modularity and reusability.
    • Preferred for UI development, where the focus is on describing the desired outcome (e.g., Angular templates, React components).
  • Imperative Programming:
    • Focuses on how to achieve a task, with explicit instructions.
    • Examples include traditional JavaScript and low-level algorithms.
    • Benefits: Offers fine-grained control, which can be useful for performance-critical tasks or complex logic.
    • Preferred for tasks requiring precise control over execution, such as algorithms or performance optimizations.

In modern frontend frameworks like Angular, a declarative approach is generally preferred for building UIs, as it aligns well with the framework’s design and improves maintainability. However, imperative programming is still valuable for specific tasks like complex state transformations or performance optimizations.

93. Would you use a state management library or a custom implementation?

The decision to use a state management library (like NgRx, Akita, or NGXS) versus a custom implementation depends on several factors:

  • Use a State Management Library When:
    • The application is large and complex, with multiple components needing access to shared state.
    • You need advanced features like time-travel debugging, undo/redo, or middleware for side effects.
    • The team is familiar with the library, or it aligns with the project’s architecture.

    Example: NgRx is a popular choice for Angular applications requiring a robust, Redux-inspired state management solution.

  • Use a Custom Implementation When:
    • The application is small or medium-sized, and shared state is minimal.
    • You want to avoid the complexity and boilerplate of a full-fledged library.
    • A simple service with RxJS subjects or BehaviorSubjects suffices for managing state.

    Example: A custom service using RxJS to manage shared state:

    
    import { Injectable } from '@angular/core';
    import { BehaviorSubject } from 'rxjs';
    
    @Injectable({ providedIn: 'root' })
    export class StateService {
      private state = new BehaviorSubject<any>(null);
      currentState$ = this.state.asObservable();
    
      updateState(newState: any) {
        this.state.next(newState);
      }
    }
                    

For most projects, starting with a custom solution and scaling up to a library if needed is a pragmatic approach. However, if the project is expected to grow significantly, investing in a state management library early can save time and effort in the long run.

94. How would you achieve parent-child component communication?

In Angular, parent-child component communication can be achieved using several methods:

  • Parent to Child: Using @Input
    • The parent component passes data to the child component using property binding.
    • The child component uses the @Input decorator to receive the data.
    
    // Parent Component
    @Component({
      selector: 'app-parent',
      template: '<app-child [childData]="parentData"></app-child>'
    })
    export class ParentComponent {
      parentData = "Hello from Parent!";
    }
    
    // Child Component
    @Component({
      selector: 'app-child',
      template: '<p>{{ childData }}</p>'
    })
    export class ChildComponent {
      @Input() childData: string;
    }
                    
  • Child to Parent: Using @Output and EventEmitter
    • The child component emits events using @Output and EventEmitter.
    • The parent component listens to these events and responds accordingly.
    
    // Child Component
    @Component({
      selector: 'app-child',
      template: '<button (click)="sendMessage()">Send Message</button>'
    })
    export class ChildComponent {
      @Output() messageEvent = new EventEmitter<string>();
    
      sendMessage() {
        this.messageEvent.emit("Hello from Child!");
      }
    }
    
    // Parent Component
    @Component({
      selector: 'app-parent',
      template: '<app-child (messageEvent)="receiveMessage($event)"></app-child>'
    })
    export class ParentComponent {
      receiveMessage(message: string) {
        console.log(message); // Output: Hello from Child!
      }
    }
                    
  • Using a Shared Service:
    • A shared service with RxJS subjects or BehaviorSubjects can facilitate communication between unrelated components.
    
    // Shared Service
    @Injectable({ providedIn: 'root' })
    export class DataService {
      private messageSource = new BehaviorSubject<string>("Default Message");
      currentMessage = this.messageSource.asObservable();
    
      changeMessage(message: string) {
        this.messageSource.next(message);
      }
    }
    
    // Parent Component
    constructor(private dataService: DataService) {
      this.dataService.changeMessage("Hello from Parent!");
    }
    
    // Child Component
    ngOnInit() {
      this.dataService.currentMessage.subscribe(message => {
        console.log(message); // Output: Hello from Parent!
      });
    }
                    
  • Using Template Reference Variables:
    • For direct communication within a template, you can use template reference variables and @ViewChild.
    
    // Parent Component
    @Component({
      selector: 'app-parent',
      template: `
        <app-child #childRef></app-child>
        <button (click)="callChildMethod()">Call Child Method</button>
      `
    })
    export class ParentComponent {
      @ViewChild('childRef') childComponent: ChildComponent;
    
      callChildMethod() {
        this.childComponent.childMethod();
      }
    }
    
    // Child Component
    @Component({
      selector: 'app-child',
      template: '<p>Child Component</p>'
    })
    export class ChildComponent {
      childMethod() {
        console.log("Child method called!");
      }
    }
                    

95. What is the role of NgZone in Angular, and when would you opt out of Angular’s change detection?

NgZone is a service in Angular that creates and manages Angular’s execution context. It is responsible for triggering change detection when asynchronous operations (like user events, timers, or HTTP requests) occur. NgZone uses Zone.js to patch browser APIs and detect these operations.

Role of NgZone:

  • Detects asynchronous operations and triggers change detection.
  • Ensures that Angular’s change detection mechanism is aware of changes that occur outside the Angular context.

Opting Out of Angular’s Change Detection:

You might opt out of Angular’s change detection in scenarios where you want to manually control when change detection runs, such as:

  • Performance optimization for components that don’t need frequent updates.
  • Integrating with third-party libraries that manage their own state and rendering.

To opt out, you can use the ChangeDetectionStrategy.OnPush strategy or detach the change detector using ChangeDetectorRef.detach() and manually trigger updates with ChangeDetectorRef.detectChanges().


import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<p>{{ message }}</p>',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExampleComponent {
  message: string = "Initial Message";

  constructor(private cdRef: ChangeDetectorRef) {}

  updateMessage() {
    this.message = "Updated Message";
    this.cdRef.detectChanges(); // Manually trigger change detection
  }
}
        

96. What is and when to use an Injection Token?

An Injection Token in Angular is a token used to look up a dependency in the dependency injection (DI) system. It is particularly useful when you need to inject a value that is not a class, such as a string, function, or object.

When to Use an Injection Token:

  • When you need to inject a non-class dependency, such as a configuration object or a string.
  • When you want to provide a value under a specific token to avoid naming collisions.

Here’s an example of creating and using an Injection Token:


import { InjectionToken } from '@angular/core';

export const APP_CONFIG = new InjectionToken<any>('app.config');

@NgModule({
  providers: [
    { provide: APP_CONFIG, useValue: { apiUrl: 'https://api.example.com' } }
  ]
})
export class AppModule {}

@Component({
  selector: 'app-example',
  template: '<p>API URL: {{ config.apiUrl }}</p>'
})
export class ExampleComponent {
  constructor(@Inject(APP_CONFIG) public config: any) {}
}
        

97. What are resolution modifiers and how to use them?

Resolution modifiers in Angular are used in the dependency injection system to control how dependencies are resolved. They allow you to specify optional dependencies, use default values, or handle cases where a dependency might not be available.

Common resolution modifiers include:

  • @Optional(): Indicates that the dependency is optional. If the dependency is not found, Angular will not throw an error.
    
    constructor(@Optional() private optionalService: OptionalService) {}
                    
  • @Inject() with a Default Value: Allows you to provide a default value if the dependency is not found.
    
    constructor(@Inject(APP_CONFIG) private config: any = { apiUrl: 'default' }) {}
                    
  • @SkipSelf(): Skips the current injector and looks for the dependency in parent injectors.
    
    constructor(@SkipSelf() private parentService: ParentService) {}
                    
  • @Host(): Limits the search for the dependency to the current host element.
    
    constructor(@Host() private hostService: HostService) {}
                    

98. Why would you use a track function in a for-loop and how it works?

In Angular, the trackBy function is used with the *ngFor directive to optimize the rendering of lists. It helps Angular identify which items in the list have changed, added, or removed, rather than re-rendering the entire list.

Why Use a Track Function:

  • Improves performance by minimizing DOM manipulations.
  • Ensures that only the changed items are updated, rather than the entire list.

How It Works:

The trackBy function returns a unique identifier for each item in the list. Angular uses this identifier to track items across renders.

Example:


@Component({
  selector: 'app-example',
  template: `
    <ul>
      <li *ngFor="let item of items; trackBy: trackById">{{ item.name }}</li>
    </ul>
  `
})
export class ExampleComponent {
  items = [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }];

  trackById(index: number, item: any): number {
    return item.id;
  }
}
        

99. What is the difference between providers and viewProviders? Can you provide an example when to use either of them?

In Angular, providers and viewProviders are used to configure dependency injection, but they differ in scope and usage:

  • providers:
    • Services provided here are available to the entire component and its child components.
    • Useful for services that need to be shared across multiple components in a module or application.
    
    @Component({
      selector: 'app-example',
      template: '...',
      providers: [ExampleService]
    })
    export class ExampleComponent {}
                    
  • viewProviders:
    • Services provided here are only available to the component’s view and its child views.
    • Useful for services that should not be available outside the component’s view hierarchy, such as services specific to a particular view encapsulation.
    
    @Component({
      selector: 'app-example',
      template: '...',
      viewProviders: [ViewSpecificService]
    })
    export class ExampleComponent {}
                    

When to Use Each:

  • Use providers for services that need to be shared across multiple components.
  • Use viewProviders for services that are specific to a component’s view and should not be accessible outside of it.

100. Why are pipes considered safe in a template, but regular function calls (not signals) are not?

In Angular, pipes are considered safe in templates for several reasons, whereas regular function calls are not:

  • Pipes:
    • Are designed to be pure by default, meaning they produce the same output for the same input and do not have side effects.
    • Are optimized for performance, as Angular caches the output of pure pipes and only recalculates them when the input changes.
    • Are declarative and easy to reason about, as they are used directly in templates.
  • Regular Function Calls:
    • Can have side effects, such as modifying component state or performing asynchronous operations.
    • Are executed every time change detection runs, which can lead to performance issues if the function is computationally expensive.
    • Are not cached, so repeated calls can cause unnecessary recalculations.

Example of a safe pipe:


@Pipe({ name: 'safePipe' })
export class SafePipe implements PipeTransform {
  transform(value: any): any {
    return value; // Pure transformation
  }
}
        

Example of an unsafe function call:


@Component({
  selector: 'app-example',
  template: '<p>{{ unsafeFunction() }}</p>'
})
export class ExampleComponent {
  unsafeFunction() {
    // This function is called during every change detection cycle
    return Math.random(); // Side effect: different output each time
  }
}
        

Pipes are designed to be safe and efficient, while regular function calls can introduce unpredictability and performance issues.

101. How would you convince your team to migrate a project from Observables to signals?

Convincing a team to migrate from Observables to signals in Angular requires highlighting the benefits of signals and addressing potential concerns. Here’s how you could approach it:

  • Simplicity: Signals provide a simpler and more intuitive way to manage state and reactivity. They reduce the complexity associated with Observables, such as managing subscriptions and handling memory leaks.
  • Performance: Signals are optimized for fine-grained reactivity, which means only the components that depend on a specific signal are updated when it changes. This can lead to better performance compared to Observables, which may trigger broader change detection cycles.
  • Easier Debugging: Signals offer better debugging capabilities, as their state and dependencies are more transparent and easier to track compared to Observables.
  • Integration with Angular: Signals are natively integrated into Angular’s change detection system, making them a more cohesive solution for state management within the framework.
  • Reduced Boilerplate: Signals eliminate the need for boilerplate code related to subscription management, such as unsubscribing in ngOnDestroy.
  • Future-Proofing: Signals are a newer feature in Angular and are likely to receive more support and improvements in the future, making the migration a strategic long-term investment.

To ease the transition, propose a phased migration plan, starting with non-critical components to demonstrate the benefits and gather feedback before scaling up.

102. Can you explain the diamond problem in Observables and why it doesn’t occur with signals?

The diamond problem in the context of Observables refers to a situation where multiple subscriptions to the same Observable can lead to unintended side effects, such as duplicate HTTP requests or inconsistent state updates. This happens because each subscription to an Observable can trigger its own independent execution.

For example, if you have an Observable that makes an HTTP request, subscribing to it multiple times will result in multiple HTTP calls:


const httpObservable = this.http.get('https://api.example.com/data');

httpObservable.subscribe(data => console.log('Subscription 1:', data));
httpObservable.subscribe(data => console.log('Subscription 2:', data));
// Both subscriptions trigger separate HTTP requests.
        

To mitigate this, you can use operators like share() or shareReplay() to multicast the Observable, ensuring that all subscribers share the same execution.

Signals, on the other hand, do not suffer from the diamond problem because they are inherently designed to manage state reactively without the need for multiple subscriptions. A signal represents a single source of truth, and all components that depend on it automatically update when the signal changes. This eliminates the risk of duplicate side effects or inconsistent state.

103. When to use effect and untracked in a signal-based application?

In a signal-based Angular application, effect and untracked serve specific purposes:

  • effect:
    • Used to perform side effects in response to signal changes.
    • An effect runs automatically whenever any of the signals it depends on change.
    • Useful for tasks like logging, updating the DOM outside of Angular, or triggering animations.
    
    import { effect } from '@angular/core';
    
    const count = signal(0);
    
    effect(() => {
      console.log(`Count changed to: ${count()}`);
    });
                    
  • untracked:
    • Used to read a signal’s value without tracking it as a dependency.
    • Prevents the effect or computed signal from re-running when the untracked signal changes.
    • Useful for breaking circular dependencies or optimizing performance by avoiding unnecessary recalculations.
    
    import { effect, untracked, signal } from '@angular/core';
    
    const count = signal(0);
    const double = signal(0);
    
    effect(() => {
      console.log(`Count: ${count()}`);
      untracked(() => {
        double.set(count() * 2);
      });
    });
                    

104. Are lifecycle hooks still needed in a fully signal-based application?

Even in a fully signal-based Angular application, lifecycle hooks are still relevant and necessary for several reasons:

  • Resource Management: Lifecycle hooks like ngOnInit and ngOnDestroy are essential for managing resources such as subscriptions, timers, or DOM manipulations that are not handled by signals.
  • Initialization and Cleanup: ngOnInit is commonly used for initialization tasks, such as fetching data or setting up component state, while ngOnDestroy is used for cleanup tasks like unsubscribing from Observables or removing event listeners.
  • Integration with Third-Party Libraries: Many third-party libraries and APIs require explicit initialization and cleanup, which can be managed using lifecycle hooks.
  • View and Change Detection: Hooks like ngAfterViewInit and ngAfterViewChecked are still useful for interacting with the DOM or handling view-related logic.

While signals simplify state management and reactivity, lifecycle hooks remain crucial for managing the broader lifecycle of components and their interactions with the environment.

105. What is a higher-order observable and how do they differ?

A higher-order Observable is an Observable that emits other Observables as values. In other words, it is an Observable of Observables. Higher-order Observables are commonly used in scenarios where you need to handle nested asynchronous operations, such as making sequential HTTP requests where each request depends on the result of the previous one.

Higher-order Observables differ from regular Observables in that they require special operators to “flatten” them into a single Observable stream. Common operators for handling higher-order Observables include:

  • mergeAll: Flattens an Observable of Observables by merging all inner Observables into a single stream.
  • switchAll: Flattens an Observable of Observables by switching to the latest inner Observable and canceling previous ones.
  • concatAll: Flattens an Observable of Observables by concatenating inner Observables in sequence.
  • exhaustMap: Ignores new inner Observables if the previous one hasn’t completed yet.

Example of a higher-order Observable:


import { of } from 'rxjs';
import { mergeAll } from 'rxjs/operators';

const higherOrderObservable = of(
  of(1, 2, 3),
  of(4, 5, 6),
  of(7, 8, 9)
);

higherOrderObservable.pipe(
  mergeAll()
).subscribe(value => {
  console.log(value); // Output: 1, 2, 3, 4, 5, 6, 7, 8, 9
});
        

106. What is the difference between share() and shareReplay()?

share() and shareReplay() are RxJS operators used to multicast Observables, but they differ in how they handle late subscribers:

  • share():
    • Multicasts the source Observable to multiple subscribers, sharing a single subscription.
    • Late subscribers will only receive values emitted after they subscribe.
    • Useful for avoiding duplicate side effects, such as multiple HTTP requests.
    
    import { interval } from 'rxjs';
    import { share, take } from 'rxjs/operators';
    
    const source = interval(1000).pipe(take(5), share());
    
    source.subscribe(value => console.log('Subscriber 1:', value));
    setTimeout(() => {
      source.subscribe(value => console.log('Subscriber 2:', value)); // Misses initial values
    }, 3000);
                    
  • shareReplay():
    • Multicasts the source Observable and replays a specified number of values to late subscribers.
    • Useful for ensuring that late subscribers receive the most recent values.
    
    import { interval } from 'rxjs';
    import { shareReplay, take } from 'rxjs/operators';
    
    const source = interval(1000).pipe(take(5), shareReplay(2));
    
    source.subscribe(value => console.log('Subscriber 1:', value));
    setTimeout(() => {
      source.subscribe(value => console.log('Subscriber 2:', value)); // Receives last 2 values
    }, 3000);
                    

107. What does this code do? – scan() + expand()

The combination of scan() and expand() in RxJS creates a powerful pattern for handling recursive or iterative asynchronous operations. Here’s what each operator does:

  • scan(): Similar to reduce, but it emits the accumulated value at each step rather than just the final result. It’s useful for maintaining state over time.
  • expand(): Recursively resubscribes to the source Observable based on its emissions. It’s useful for implementing recursive algorithms or handling nested asynchronous operations.

When combined, scan() + expand() can be used to create a recursive state machine or handle complex iterative logic. For example:


import { of } from 'rxjs';
import { scan, expand, take } from 'rxjs/operators';

of(1).pipe(
  expand(value => value < 5 ? of(value + 1) : EMPTY),
  scan((acc, value) => acc + value, 0),
  take(5)
).subscribe(value => {
  console.log(value); // Output: 1, 3, 6, 10, 15
});
        

In this example, expand() recursively emits values from 1 to 5, and scan() accumulates the sum of these values.

108. What are the advantages of Angular?

Angular offers several advantages that make it a popular choice for building modern web applications:

  • Component-Based Architecture: Encourages modularity and reusability, making it easier to manage and scale applications.
  • Two-Way Data Binding: Simplifies synchronization between the model and the view, reducing boilerplate code.
  • Dependency Injection: Promotes modularity and testability by managing dependencies efficiently.
  • TypeScript Support: Provides static typing, better tooling, and improved maintainability compared to JavaScript.
  • Comprehensive Ecosystem: Includes tools like Angular CLI for scaffolding, testing, and deployment, as well as libraries for routing, forms, and HTTP client.
  • Performance Optimization: Features like Ahead-of-Time (AOT) compilation and lazy loading improve application performance.
  • Cross-Platform Development: Supports building web, mobile, and desktop applications using the same codebase.
  • Strong Community and Support: Backed by Google and a large community, ensuring continuous improvements and extensive resources.

109. Why is TypeScript used in Angular?

Angular uses TypeScript for several compelling reasons:

  • Static Typing: TypeScript provides static typing, which helps catch errors during development and improves code quality.
  • Enhanced Tooling: TypeScript supports advanced tooling, such as autocompletion, refactoring, and navigation, which enhances developer productivity.
  • Better Maintainability: TypeScript’s features, such as interfaces, enums, and decorators, make the codebase more maintainable and easier to understand.
  • Compatibility: TypeScript is a superset of JavaScript, meaning any valid JavaScript code is also valid TypeScript. This ensures compatibility with existing JavaScript libraries and code.
  • Modern Features: TypeScript supports modern JavaScript features, such as classes, modules, and arrow functions, along with additional features like generics and decorators.
  • Improved Collaboration: TypeScript’s type definitions and interfaces make it easier for teams to collaborate and understand the codebase.
  • Angular Integration: Angular is built with TypeScript, and its features, such as decorators for components and services, are designed to work seamlessly with TypeScript.

110. What type of data binding does Angular use?

Angular supports several types of data binding to synchronize data between the model (component) and the view (template):

  • Interpolation ({{ data }}): One-way binding from the component to the view.
    
    <p>{{ message }}</p>
                    
  • Property Binding ([property]="data"): One-way binding from the component to an element property.
    
    <img [src]="imageUrl">
                    
  • Event Binding ((event)="handler()"): One-way binding from the view to the component.
    
    <button (click)="onClick()">Click Me</button>
                    
  • Two-Way Binding ([(ngModel)]="data"): Synchronizes data between the component and the view.
    
    <input [(ngModel)]="userName">
                    

These data binding types allow developers to create dynamic and interactive user interfaces efficiently.

111. What technologies does Angular use under the hood?

Angular leverages several technologies and libraries under the hood to provide its powerful features and performance optimizations:

  • TypeScript: Angular is built using TypeScript, which provides static typing, modern JavaScript features, and better tooling support.
  • RxJS: Used for reactive programming with Observables, enabling Angular to handle asynchronous operations like HTTP requests and user events efficiently.
  • Zone.js: A library that enables Angular’s change detection by patching asynchronous browser APIs to trigger change detection cycles.
  • Ivy Renderer: Angular’s rendering engine, which compiles components to highly optimized JavaScript code, improving performance and reducing bundle size.
  • Web Components: Angular supports Web Components, allowing components to be used across different frameworks or vanilla JavaScript.
  • Differential Loading: Angular CLI generates separate bundles for modern and legacy browsers, ensuring compatibility and optimal performance.
  • Tree Shaking: Removes unused code during the build process, reducing the final bundle size.
  • AOT (Ahead-of-Time) Compilation: Compiles Angular templates to JavaScript during the build process, improving runtime performance.

112. How does Angular’s dependency injection system work?

Angular’s dependency injection (DI) system is a core feature that allows components and services to declare their dependencies without managing their instantiation. Here’s how it works:

  • Injector Hierarchy: Angular maintains a hierarchy of injectors at different levels (e.g., root, module, component). Each injector is responsible for creating and managing instances of dependencies.
  • Providers: Dependencies are registered as providers in modules or components. Providers define how an object should be instantiated and can be configured to use classes, values, or factories.
  • Dependency Resolution: When a component or service requests a dependency, Angular’s DI system resolves it by looking up the injector hierarchy to find the appropriate provider.
  • Singleton Services: By default, services provided at the root level are singletons, meaning a single instance is shared across the application.
  • Dependency Injection Tokens: Tokens are used to identify dependencies. These can be classes, strings, or InjectionToken objects.

Example of DI in Angular:


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root' // Registers the service as a singleton at the root level
})
export class DataService {
  getData() {
    return "Data from service";
  }
}
        

import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-example',
  template: '<p>{{ data }}</p>'
})
export class ExampleComponent {
  data: string;

  constructor(private dataService: DataService) {
    this.data = this.dataService.getData();
  }
}
        

113. What is the purpose of async pipes in Angular?

The async pipe in Angular is used to automatically subscribe to Observables or Promises and update the view with the emitted values. It simplifies the process of handling asynchronous data by:

  • Automatically subscribing to the Observable or Promise.
  • Updating the view whenever new data is emitted.
  • Automatically unsubscribing when the component is destroyed, preventing memory leaks.

Example of using the async pipe:


import { Component } from '@angular/core';
import { Observable, of } from 'rxjs';

@Component({
  selector: 'app-example',
  template: '<p>{{ data$ | async }}</p>'
})
export class ExampleComponent {
  data$: Observable = of("Hello, Angular!");
}
        

The async pipe is particularly useful for displaying data from HTTP requests or other asynchronous operations without manually managing subscriptions.

114. What are the change detection strategies in Angular?

Angular uses change detection to update the view whenever the application state changes. There are two primary change detection strategies:

  • Default Strategy:
    • Angular checks every component for changes whenever an event (e.g., user input, timer, HTTP response) occurs.
    • This strategy ensures that the view is always up-to-date but can impact performance in large applications.
  • OnPush Strategy:
    • Angular only checks a component for changes when its input properties change or when an event originates from the component or its children.
    • This strategy improves performance by reducing the number of change detection cycles.
    • Components using the OnPush strategy must use immutable data or signals to ensure proper change detection.
    
    import { Component, ChangeDetectionStrategy } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: '<p>{{ message }}</p>',
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class ExampleComponent {
      message: string = "Hello, Angular!";
    }
                    

115. What are FormsModule and ReactiveFormsModule?

Angular provides two modules for handling forms:

  • FormsModule:
    • Used for template-driven forms, where form controls are defined in the template using directives like ngModel.
    • Simpler to set up and suitable for basic forms with minimal validation.
    
    import { FormsModule } from '@angular/forms';
    
    @NgModule({
      imports: [FormsModule]
    })
    export class AppModule {}
                    
    
    <form>
      <input [(ngModel)]="user.name" name="name">
    </form>
                    
  • ReactiveFormsModule:
    • Used for reactive forms, where form controls are defined programmatically in the component class.
    • Provides explicit control over form validation and state, making it suitable for complex forms with dynamic controls and advanced validation.
    
    import { ReactiveFormsModule } from '@angular/forms';
    
    @NgModule({
      imports: [ReactiveFormsModule]
    })
    export class AppModule {}
                    
    
    import { FormBuilder, FormGroup } from '@angular/forms';
    
    @Component({
      selector: 'app-example',
      template: `
        <form [formGroup]="form">
          <input formControlName="name">
        </form>
      `
    })
    export class ExampleComponent {
      form: FormGroup;
    
      constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
          name: ['']
        });
      }
    }
                    

116. What methods can be used to update the view in Angular?

In Angular, several methods can be used to update the view in response to changes in the application state:

  • Data Binding: Angular’s data binding mechanisms (interpolation, property binding, event binding, and two-way binding) automatically update the view when the underlying data changes.
  • Change Detection: Angular’s change detection mechanism automatically updates the view when it detects changes in component properties or application state.
  • Manual Change Detection: In some cases, you can manually trigger change detection using ChangeDetectorRef.
    
    import { Component, ChangeDetectorRef } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: '<p>{{ message }}</p>'
    })
    export class ExampleComponent {
      message: string = "Initial Message";
    
      constructor(private cdRef: ChangeDetectorRef) {}
    
      updateMessage() {
        this.message = "Updated Message";
        this.cdRef.detectChanges(); // Manually trigger change detection
      }
    }
                    
  • Async Pipe: The async pipe automatically updates the view when an Observable or Promise emits new values.
  • Signals: In signal-based applications, changes to signals automatically trigger view updates.

117. When should inline templates be used versus external templates?

The choice between inline templates and external templates in Angular depends on the complexity and maintainability of your components:

  • Inline Templates:
    • Defined directly in the component decorator using the template property.
    • Suitable for small, simple components where the template is short and easy to read.
    • Example:
      
      @Component({
        selector: 'app-example',
        template: '<p>Hello, Angular!</p>'
      })
      export class ExampleComponent {}
                              
  • External Templates:
    • Defined in separate HTML files and referenced in the component decorator using the templateUrl property.
    • Suitable for larger, more complex components where the template is lengthy or requires better organization.
    • Example:
      
      @Component({
        selector: 'app-example',
        templateUrl: './example.component.html'
      })
      export class ExampleComponent {}
                              

Inline templates are convenient for small components, while external templates are better for maintaining readability and organization in larger components.

118. What are decorators in Angular?

Decorators in Angular are special functions that modify or enhance the behavior of classes, methods, properties, or parameters. They are a TypeScript feature that Angular uses extensively to define metadata and configure how classes are processed.

Decorators are applied using the @ symbol and are used for various purposes, such as defining components, directives, and services.

119. What are the types of decorators in Angular?

Angular uses several types of decorators, each serving a specific purpose:

  • Class Decorators:
    • Applied to classes to define their role in the application.
    • Examples: @Component, @Directive, @Injectable, @NgModule.
    
    @Component({
      selector: 'app-example',
      template: '<p>Hello, Angular!</p>'
    })
    export class ExampleComponent {}
                    
  • Property Decorators:
    • Applied to properties to define their behavior or metadata.
    • Examples: @Input, @Output, @ViewChild.
    
    @Input() inputProperty: string;
    @Output() outputEvent = new EventEmitter<string>();
                    
  • Method Decorators:
    • Applied to methods to modify their behavior.
    • Less commonly used in Angular but can be used for custom logic or logging.
  • Parameter Decorators:
    • Applied to parameters to define their behavior or metadata.
    • Examples: @Inject, @Optional.
    
    constructor(@Inject('API_URL') private apiUrl: string) {}
                    

120. Why is lazy loading of modules required in Angular?

Lazy loading of modules in Angular is required for several reasons:

  • Performance Optimization: Lazy loading improves the initial load time of the application by loading only the necessary modules when they are needed, rather than loading everything upfront.
  • Reduced Bundle Size: By splitting the application into smaller chunks, lazy loading reduces the size of the initial bundle, which is especially beneficial for large applications.
  • Efficient Resource Usage: Modules are loaded on-demand, reducing memory usage and improving the overall user experience.
  • Scalability: Lazy loading makes it easier to scale the application by adding new features without significantly impacting the initial load time.

Example of lazy loading in Angular:


const routes: Routes = [
  { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];
        

In this example, the LazyModule is loaded only when the user navigates to the /lazy route.

121. What are template-driven forms in Angular?

Template-driven forms in Angular are a way to create forms where the form controls and validation are defined directly in the template using directives. This approach relies on Angular’s built-in directives like ngModel to bind form inputs to component properties and manage form state.

Template-driven forms are simpler to set up and are suitable for basic forms with minimal validation requirements. They use two-way data binding to keep the model and view in sync.

Example of a template-driven form:


import { Component } from '@angular/core';

@Component({
  selector: 'app-template-form',
  template: `
    <form>
      <input [(ngModel)]="user.name" name="name" placeholder="Name">
      <input [(ngModel)]="user.email" name="email" placeholder="Email">
    </form>
  `
})
export class TemplateFormComponent {
  user = {
    name: '',
    email: ''
  };
}
        

To use template-driven forms, you need to import the FormsModule from @angular/forms in your Angular module.

122. What is the purpose of the Shared module and Core module in Angular?

In Angular, Shared modules and Core modules serve distinct purposes to organize and manage code effectively:

  • Shared Module:
    • Contains components, directives, and pipes that are used across multiple feature modules.
    • Promotes reusability and reduces code duplication.
    • Should only include declarables (components, directives, pipes) and avoid providing services to prevent duplicate instances.
    
    @NgModule({
      declarations: [SharedComponent, SharedDirective],
      exports: [SharedComponent, SharedDirective]
    })
    export class SharedModule {}
                    
  • Core Module:
    • Contains singleton services, application-wide components, and other utilities that should be loaded only once.
    • Should be imported only once in the root module (AppModule).
    • Helps manage global services and configurations.
    
    @NgModule({
      providers: [AuthService, LoggerService]
    })
    export class CoreModule {}
                    

123. What is unit testing and integration testing in Angular?

Unit testing and integration testing are essential for ensuring the reliability and correctness of Angular applications:

  • Unit Testing:
    • Focuses on testing individual components, services, or functions in isolation.
    • Uses frameworks like Jasmine for writing tests and Karma for running them.
    • Helps catch bugs early and ensures that each unit of code works as expected.
    
    import { TestBed } from '@angular/core/testing';
    import { ExampleService } from './example.service';
    
    describe('ExampleService', () => {
      let service: ExampleService;
    
      beforeEach(() => {
        TestBed.configureTestingModule({});
        service = TestBed.inject(ExampleService);
      });
    
      it('should be created', () => {
        expect(service).toBeTruthy();
      });
    });
                    
  • Integration Testing:
    • Focuses on testing the interaction between multiple components, services, or modules.
    • Ensures that different parts of the application work together correctly.
    • Can involve testing components with their templates, services, and dependencies.
    
    import { ComponentFixture, TestBed } from '@angular/core/testing';
    import { ExampleComponent } from './example.component';
    
    describe('ExampleComponent', () => {
      let component: ExampleComponent;
      let fixture: ComponentFixture<ExampleComponent>;
    
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [ExampleComponent]
        }).compileComponents();
    
        fixture = TestBed.createComponent(ExampleComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    });
                    

124. What are Angular Templates?

Angular templates are HTML files that define the user interface of a component. They combine standard HTML with Angular-specific syntax, such as directives, bindings, and pipes, to create dynamic and interactive views.

Templates are associated with components and define how the component’s data is rendered in the browser. They can include:

  • Data bindings to display component properties.
  • Directives to add dynamic behavior.
  • Event bindings to respond to user actions.
  • Pipes to transform data before displaying it.

Example of an Angular template:


<h1>{{ title }}</h1>
<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>
<button (click)="onClick()">Click Me</button>
        

125. What is the ngFor directive used for?

The *ngFor directive in Angular is used to iterate over a collection (such as an array) and render a template for each item in the collection. It is a structural directive that dynamically adds and removes elements from the DOM based on the data.

Example of using *ngFor:


<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>
        

You can also use the index and trackBy options with *ngFor:


<ul>
  <li *ngFor="let item of items; let i = index; trackBy: trackById">
    {{ i }}: {{ item }}
  </li>
</ul>
        

The trackBy function helps optimize rendering by tracking items by a unique identifier.

126. What is the purpose of the ngIf directive?

The *ngIf directive in Angular is used to conditionally include or exclude a portion of the template based on a boolean expression. If the expression evaluates to true, the element is added to the DOM; if it evaluates to false, the element is removed from the DOM.

Example of using *ngIf:


<p *ngIf="isVisible">This text is visible!</p>
<p *ngIf="!isVisible">This text is hidden.</p>
        

You can also use *ngIf with an else clause:


<p *ngIf="isVisible; else elseBlock">This text is visible!</p>
<ng-template #elseBlock>
  <p>This text is hidden.</p>
</ng-template>
        

127. What is a template expression in Angular?

A template expression in Angular is a TypeScript-like expression that is evaluated within the context of a component and used in templates to display dynamic content. Template expressions are enclosed in double curly braces {{ }} and can include:

  • Component properties.
  • Method calls.
  • Simple arithmetic or logical operations.

Example of a template expression:


<p>{{ message }}</p>
<p>{{ 1 + 1 }}</p>
<p>{{ getMessage() }}</p>
        

Template expressions are designed to be simple and safe, avoiding side effects and complex logic.

128. What are template statements in Angular?

Template statements in Angular are TypeScript-like statements that respond to events in the template. They are used in event bindings to execute logic when events (such as clicks or input changes) occur. Template statements are enclosed in quotes and can include:

  • Method calls.
  • Property assignments.
  • Simple expressions.

Example of a template statement:


<button (click)="onClick()">Click Me</button>
<input (input)="onInput($event)">
        

Template statements should be simple and avoid complex logic to maintain readability and performance.

129. What are custom elements in Angular?

Custom elements in Angular refer to the ability to create and use Angular components as Web Components. This allows Angular components to be used in non-Angular environments, such as vanilla JavaScript applications or other frameworks. Custom elements are defined using the @angular/elements package.

Custom elements are useful for:

  • Creating reusable components that can be used across different frameworks.
  • Integrating Angular components into existing applications without requiring a full Angular setup.

Example of creating a custom element:


import { createCustomElement } from '@angular/elements';
import { AppComponent } from './app.component';
import { NgModule, Injector } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

@NgModule({
  imports: [BrowserModule],
  entryComponents: [AppComponent]
})
export class AppModule {
  constructor(private injector: Injector) {}

  ngDoBootstrap() {
    const customElement = createCustomElement(AppComponent, { injector: this.injector });
    customElements.define('my-custom-element', customElement);
  }
}
        

130. Do custom elements need to be bootstrapped in Angular?

No, custom elements created using Angular Elements do not need to be bootstrapped in the traditional Angular sense. Instead, they are registered as custom elements using the browser’s customElements.define method. This allows them to be used like standard HTML elements in any web page or application.

Once defined, custom elements can be used directly in HTML:


<my-custom-element></my-custom-element>
        

Custom elements are self-bootstrapping and do not require Angular’s bootstrapping process, making them highly portable and reusable across different environments.

131. How can components be transferred to custom elements?

To transfer an Angular component to a custom element, you can use Angular Elements, which allows you to package Angular components as Web Components. Here’s a step-by-step guide:

  1. Install Angular Elements: Add the @angular/elements package to your project.
    
    npm install @angular/elements
                    
  2. Create a Custom Element: Use the createCustomElement function to convert an Angular component into a custom element.
    
    import { createCustomElement } from '@angular/elements';
    import { AppComponent } from './app.component';
    import { NgModule, Injector } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    
    @NgModule({
      imports: [BrowserModule],
      entryComponents: [AppComponent]
    })
    export class AppModule {
      constructor(private injector: Injector) {}
    
      ngDoBootstrap() {
        const customElement = createCustomElement(AppComponent, { injector: this.injector });
        customElements.define('my-custom-element', customElement);
      }
    }
                    
  3. Define the Custom Element: Register the custom element using customElements.define.
  4. Use the Custom Element: Once defined, you can use the custom element in any HTML page or application.
    
    <my-custom-element></my-custom-element>
                    

This process allows you to leverage Angular components in non-Angular environments, making them highly reusable.

132. What does REST stand for?

REST stands for Representational State Transfer. It is an architectural style for designing networked applications, typically used in web services. REST relies on stateless, client-server communication over HTTP and emphasizes the use of standard HTTP methods (GET, POST, PUT, DELETE, etc.) to perform operations on resources.

Key principles of REST include:

  • Statelessness: Each request from a client to a server must contain all the information needed to understand and process the request.
  • Resource-Based: Resources are identified by URIs (Uniform Resource Identifiers).
  • Standard HTTP Methods: Use HTTP methods (GET, POST, PUT, DELETE) to perform CRUD operations on resources.
  • Representation: Resources can be represented in various formats, such as JSON or XML.

133. What are the steps to use HttpClient in Angular?

To use HttpClient in Angular for making HTTP requests, follow these steps:

  1. Import HttpClientModule: Add HttpClientModule to your Angular module.
    
    import { HttpClientModule } from '@angular/common/http';
    
    @NgModule({
      imports: [HttpClientModule]
    })
    export class AppModule {}
                    
  2. Inject HttpClient: Inject the HttpClient service into your component or service.
    
    import { HttpClient } from '@angular/common/http';
    
    constructor(private http: HttpClient) {}
                    
  3. Make HTTP Requests: Use the HttpClient methods to make HTTP requests.
    
    this.http.get('https://api.example.com/data').subscribe(data => {
      console.log(data);
    });
                    
  4. Handle Responses and Errors: Use RxJS operators to handle responses and errors.
    
    this.http.get('https://api.example.com/data').pipe(
      catchError(error => {
        console.error('Error:', error);
        return of(null);
      })
    ).subscribe(data => {
      console.log(data);
    });
                    

134. What are the types of view encapsulation in Angular?

Angular provides three types of view encapsulation to control how styles are applied to components:

  • ViewEncapsulation.Emulated (default):
    • Angular emulates shadow DOM behavior by adding unique attributes to component elements and scoping styles to those attributes.
  • ViewEncapsulation.Native:
    • Uses the browser’s native shadow DOM to encapsulate styles. This is not widely supported across all browsers.
  • ViewEncapsulation.None:
    • Styles are globally applied without any encapsulation, affecting all elements on the page.

Example of setting view encapsulation:


import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css'],
  encapsulation: ViewEncapsulation.Emulated
})
export class ExampleComponent {}
        

135. What are AngularJS controllers?

In AngularJS, controllers are JavaScript functions that provide data and logic to HTML views. They act as intermediaries between the model (data) and the view (HTML), handling user interactions and updating the view accordingly.

Controllers are typically defined using the ng-controller directive in the HTML or by associating them with routes.

Example of an AngularJS controller:


angular.module('myApp', [])
  .controller('MyController', function($scope) {
    $scope.message = "Hello, AngularJS!";
  });
        

In the HTML:


<div ng-controller="MyController">
  <p>{{ message }}</p>
</div>
        

136. What is content projection in Angular?

Content projection in Angular is a technique that allows you to insert content from a parent component into a child component. This is achieved using the <ng-content> element in the child component’s template.

Content projection is useful for creating reusable and flexible components that can accept dynamic content.

Example of content projection:


// Child Component
@Component({
  selector: 'app-child',
  template: '<ng-content></ng-content>'
})
export class ChildComponent {}
        

// Parent Component Template
<app-child>
  <p>This content is projected into the child component.</p>
</app-child>
        

137. What is Renderer2 in Angular?

Renderer2 in Angular is a service that provides an abstraction layer for manipulating the DOM in a platform-agnostic way. It allows you to create, update, and remove elements without directly accessing the DOM, which is particularly useful for server-side rendering and web workers.

Renderer2 helps prevent direct DOM manipulation, which can lead to security vulnerabilities like XSS attacks. It also ensures that your code works consistently across different platforms.

Example of using Renderer2:


import { Component, Renderer2, OnInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<div #myDiv>Hello</div>'
})
export class ExampleComponent implements OnInit {
  constructor(private renderer: Renderer2) {}

  ngOnInit() {
    const div = this.renderer.createElement('div');
    const text = this.renderer.createText('World');
    this.renderer.appendChild(div, text);
    this.renderer.appendChild(document.body, div);
  }
}
        

138. What is the difference between Renderer2 and ElementRef?

Renderer2 and ElementRef in Angular serve different purposes when it comes to interacting with the DOM:

  • Renderer2:
    • Provides an abstraction layer for DOM manipulation, ensuring that code works across different platforms (e.g., browser, server).
    • Used for creating, updating, and removing DOM elements in a safe and platform-agnostic way.
    • Helps prevent security risks like XSS attacks by avoiding direct DOM access.
  • ElementRef:
    • Provides direct access to a DOM element.
    • Wraps the native element and allows you to interact with it directly.
    • Should be used cautiously, as direct DOM manipulation can lead to security vulnerabilities and platform incompatibilities.

Example of using ElementRef:


import { Component, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<div #myDiv>Hello</div>'
})
export class ExampleComponent implements AfterViewInit {
  constructor(private elementRef: ElementRef) {}

  ngAfterViewInit() {
    const div = this.elementRef.nativeElement.querySelector('#myDiv');
    div.textContent = 'Hello, World!';
  }
}
        

139. What is Zone.js in Angular?

Zone.js is a library used by Angular to handle asynchronous operations. It provides a mechanism called “Zones” that allows Angular to detect when asynchronous tasks (such as user events, timers, or HTTP requests) occur and trigger change detection accordingly.

Key purposes of Zone.js in Angular:

  • Monitors asynchronous operations to determine when to run change detection.
  • Ensures that Angular’s change detection mechanism is aware of changes that occur outside the Angular context.
  • Simplifies the process of managing asynchronous tasks by providing a consistent way to patch and track them.

140. What is a race condition in Angular?

A race condition in Angular (or any asynchronous programming context) occurs when the behavior of a program depends on the timing or sequence of uncontrollable events, leading to unpredictable results. This often happens when multiple asynchronous operations access and modify shared data simultaneously.

Common scenarios where race conditions can occur in Angular:

  • Multiple HTTP requests updating the same state.
  • Concurrent user interactions triggering conflicting state changes.
  • Asynchronous operations that depend on the order of execution.

To mitigate race conditions, you can use techniques such as:

  • Using RxJS operators like switchMap, concatMap, or mergeMap to control the order of asynchronous operations.
  • Implementing locks or guards to ensure that only one operation can modify shared state at a time.
  • Using state management libraries like NgRx to manage state changes in a predictable manner.

141. How are asynchronous operations handled in JavaScript?

Asynchronous operations in JavaScript are handled using several mechanisms that allow non-blocking execution of code. Here are the primary ways:

  • Callbacks: Functions passed as arguments to be executed after an asynchronous operation completes.
    
    function fetchData(callback) {
      setTimeout(() => {
        callback('Data fetched');
      }, 1000);
    }
    
    fetchData(data => {
      console.log(data); // Output: Data fetched
    });
                    
  • Promises: Objects representing the eventual completion (or failure) of an asynchronous operation and its resulting value.
    
    const fetchData = () => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve('Data fetched');
        }, 1000);
      });
    };
    
    fetchData().then(data => {
      console.log(data); // Output: Data fetched
    });
                    
  • Async/Await: Syntactic sugar over Promises, allowing asynchronous code to be written in a synchronous style.
    
    async function fetchData() {
      const response = await new Promise((resolve) => {
        setTimeout(() => {
          resolve('Data fetched');
        }, 1000);
      });
      console.log(response); // Output: Data fetched
    }
    
    fetchData();
                    
  • Observables (RxJS): Used in Angular for handling streams of data over time. Observables provide powerful operators for managing asynchronous data flows.
    
    import { of } from 'rxjs';
    
    const data$ = of('Data fetched');
    
    data$.subscribe(data => {
      console.log(data); // Output: Data fetched
    });
                    

142. What are HostBinding and HostListener in Angular?

HostBinding and HostListener are decorators in Angular used to bind properties and listen to events on the host element of a directive or component.

  • HostBinding: Binds a host element property (e.g., class, style, or attribute) to a component or directive property.
    
    import { Directive, HostBinding } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective {
      @HostBinding('class.highlighted') isHighlighted = true;
    }
                    
  • HostListener: Listens to events on the host element and executes a method when the event occurs.
    
    import { Directive, HostListener } from '@angular/core';
    
    @Directive({
      selector: '[appClick]'
    })
    export class ClickDirective {
      @HostListener('click', ['$event'])
      onClick(event: Event) {
        console.log('Element clicked', event);
      }
    }
                    

143. What are the ways to clone an object in Angular?

Cloning an object in Angular (or JavaScript) can be done in several ways, depending on the complexity of the object and whether it contains nested objects or functions. Here are common methods:

  • Spread Operator: Creates a shallow copy of an object.
    
    const original = { a: 1, b: 2 };
    const clone = { ...original };
                    
  • Object.assign: Also creates a shallow copy of an object.
    
    const original = { a: 1, b: 2 };
    const clone = Object.assign({}, original);
                    
  • JSON.parse and JSON.stringify: Creates a deep copy of an object, but loses functions and special properties like Date or RegExp.
    
    const original = { a: 1, b: { c: 2 } };
    const clone = JSON.parse(JSON.stringify(original));
                    
  • Lodash’s cloneDeep: A utility function from the Lodash library that creates a deep copy of an object.
    
    import { cloneDeep } from 'lodash';
    
    const original = { a: 1, b: { c: 2 } };
    const clone = cloneDeep(original);
                    

144. What does the bootstrap method do in Angular?

In Angular, the bootstrap method is used to start or initialize an Angular application. It specifies the root component that Angular should use to launch the application. This method is typically defined in the main.ts file.

Example of bootstrapping an Angular application:


import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));
        

In this example, bootstrapModule is called with the root module (AppModule), which defines the root component (AppComponent) to be rendered.

145. How can non-primitive types be detected in Angular?

In Angular (or JavaScript/TypeScript), you can detect non-primitive types (objects, arrays, functions, etc.) using various methods. Here are some common techniques:

  • typeof Operator: Helps identify the type of a variable, but note that it returns "object" for objects, arrays, and null.
    
    const obj = { a: 1 };
    console.log(typeof obj); // Output: "object"
                    
  • instanceof Operator: Checks if an object is an instance of a specific class or constructor.
    
    const arr = [1, 2, 3];
    console.log(arr instanceof Array); // Output: true
                    
  • Array.isArray: Specifically checks if a value is an array.
    
    const arr = [1, 2, 3];
    console.log(Array.isArray(arr)); // Output: true
                    
  • Custom Type Guards: Use TypeScript type guards to check for specific types.
    
    function isObject(value: any): value is object {
      return value !== null && typeof value === 'object';
    }
    
    const obj = { a: 1 };
    console.log(isObject(obj)); // Output: true
                    

146. What is the difference between sessionStorage and localStorage?

sessionStorage and localStorage are both web storage APIs used to store key-value pairs in a web browser, but they differ in scope and persistence:

  • sessionStorage:
    • Stores data for the duration of a browser session.
    • Data is cleared when the browser tab or window is closed.
    • Accessible only within the same tab or window.
  • localStorage:
    • Stores data with no expiration time.
    • Data persists even after the browser is closed and reopened.
    • Accessible across all tabs and windows of the same origin.

Example of using sessionStorage and localStorage:


// Using sessionStorage
sessionStorage.setItem('key', 'value');
const sessionValue = sessionStorage.getItem('key');

// Using localStorage
localStorage.setItem('key', 'value');
const localValue = localStorage.getItem('key');
        

147. What is an AOT Compiler?

The AOT (Ahead-of-Time) Compiler in Angular is a tool that compiles Angular applications during the build phase, before they are deployed to the browser. This is in contrast to JIT (Just-in-Time) compilation, where the application is compiled in the browser at runtime.

Advantages of AOT:

  • Faster Rendering: The browser downloads a pre-compiled version of the application, which renders faster.
  • Smaller Bundle Size: AOT compilation reduces the size of the application bundle by eliminating unnecessary Angular compiler code.
  • Early Error Detection: Errors like template binding issues are caught during the build process rather than at runtime.
  • Improved Security: AOT compiles templates into JavaScript, which reduces the risk of injection attacks.

AOT is enabled by default in Angular CLI for production builds.

148. How many types of compilation does Angular provide?

Angular provides two types of compilation:

  • JIT (Just-in-Time) Compilation:
    • Compiles the application in the browser at runtime.
    • Useful for development due to faster rebuilds and easier debugging.
  • AOT (Ahead-of-Time) Compilation:
    • Compiles the application during the build phase, before it is deployed to the browser.
    • Provides better performance, smaller bundle sizes, and early error detection.
    • Used for production builds.

149. What is a factory method in AngularJS?

In AngularJS, a factory method is a function used to create and configure services. Factories are one of the ways to define services in AngularJS, allowing you to encapsulate logic and data that can be shared across components.

Example of a factory in AngularJS:


angular.module('myApp', [])
  .factory('DataService', function() {
    return {
      getData: function() {
        return "Data from factory";
      }
    };
  });
        

In this example, DataService is a factory that provides a method getData. Factories are useful for creating reusable services with custom logic.

150. What is the digest cycle in AngularJS?

The digest cycle in AngularJS is the process by which AngularJS monitors watchers to track changes in the model and updates the view accordingly. It ensures that the view is always synchronized with the model.

Key points about the digest cycle:

  • Watchers: AngularJS sets up watchers on scope properties to detect changes.
  • Dirty Checking: The digest cycle performs dirty checking to determine if any watchers have changed.
  • Triggering: The digest cycle can be triggered manually using $scope.$apply() or automatically by AngularJS events like ng-click or $timeout.
  • Performance Impact: A large number of watchers can slow down the application, as each digest cycle must check all watchers for changes.

Example of triggering the digest cycle manually:


angular.module('myApp', [])
  .controller('MyController', function($scope) {
    $scope.message = "Hello, AngularJS!";

    setTimeout(function() {
      $scope.$apply(function() {
        $scope.message = "Updated message";
      });
    }, 1000);
  });
        

Latest Post

Share:
Previous: 150 Top-Asked Agile & Scrum Interview Questions in 2026
Next: 200 ADO.NET Interview Questions and Answers for 2026
New100 Docker Interview Questions and Answers

100 Docker Interview Questions and Answers

100 Docker Interview Questions and Answers for 2026 1. What is Docker? Docker is an open-source platform designed to automate…

By Question Mentor
200 Top Node.js Javascript Interview Questions and Answers

200 Top Node.js Javascript Interview Questions and Answers

Top Node.js Interview Questions and Answers for 2025 1. What is Node.js and how does it work? Node.js is an…

By Question Mentor
150 Top-Asked Agile & Scrum Interview Questions in 2026

150 Top-Asked Agile & Scrum Interview Questions in 2026

Having spent over a decade coaching teams through Agile transformations, I’ve watched the landscape evolve from niche methodology to near-universal…

By Question Mentor
FEEDBACK