Angular top interview questions and answers

 

// Question 1: What are Angular decorators and how do they work?

 

// Answer:

// Decorators in Angular are design patterns used to define metadata about classes, methods, properties, and parameters. They are prefixed with the "@" symbol and used to attach specific functionality to the element they are decorating. Angular uses these decorators to understand the structure and behavior of different elements like components, directives, pipes, etc.

 

// Example:

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

 

@Component({

  selector: 'app-example',

  template: '<h1>Hello, {{name}}</h1>',

})

export class ExampleComponent {

  @Input() name: string;

}

 

// Question 2: What is Angular's dependency injection and how does it work?

 

// Answer:

// Dependency Injection (DI) is a design pattern used in Angular to manage dependencies of various components and services. Angular's DI framework allows you to inject dependencies into a component or service, rather than having the component/service create them itself. This promotes better modularity and ease of testing.

 

// Example:

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

 

@Injectable({

  providedIn: 'root',

})

export class DataService {

  getData() {

    return ['Data 1', 'Data 2', 'Data 3'];

  }

}

 

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

import { DataService } from './data.service';

 

@Component({

  selector: 'app-root',

  template: '<ul><li *ngFor="let item of data">{{item}}</li></ul>',

})

export class AppComponent {

  data: string[];

 

  constructor(private dataService: DataService) {

    this.data = this.dataService.getData();

  }

}

 

// Question 3: Explain the difference between Observable and Promise in Angular.

 

// Answer:

// Observables and Promises are used to handle asynchronous data. Promises handle a single event when an async operation completes or fails, while Observables are more powerful and can handle multiple events over time. Observables are lazy, meaning they only execute when subscribed to, and provide multiple operators to transform, filter, and combine streams of data.

 

// Example:

import { Observable } from 'rxjs';

 

const observable = new Observable(observer => {

  setTimeout(() => {

    observer.next('Hello from Observable!');

    observer.complete();

  }, 1000);

});

 

observable.subscribe({

  next: value => console.log(value),

  complete: () => console.log('Observable complete'),

});

 

const promise = new Promise((resolve, reject) => {

  setTimeout(() => {

    resolve('Hello from Promise!');

  }, 1000);

});

 

promise.then(value => console.log(value));

 

// Question 4: What is Angular CLI and how do you use it?

 

// Answer:

// Angular CLI (Command Line Interface) is a powerful tool that helps to initialize, develop, scaffold, and maintain Angular applications. It provides commands to create components, services, pipes, directives, and more, as well as to build and serve the application.

 

// Example Commands:

// Create a new Angular project: `ng new my-angular-app`

// Serve the application: `ng serve`

// Generate a new component: `ng generate component my-component`

 

// Question 5: How does Angular handle forms? Explain Template-driven vs. Reactive forms.

 

// Answer:

// Angular supports two types of forms: Template-driven and Reactive forms. Template-driven forms rely on directives in the template to create and manipulate the form controls, suitable for simple forms. Reactive forms provide a model-driven approach to handle form inputs, offering more control and flexibility, suitable for complex forms.

 

// Example of Template-driven form:

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

 

@Component({

  selector: 'app-template-form',

  template: `

    <form #form="ngForm" (ngSubmit)="onSubmit(form)">

      <input name="name" ngModel required>

      <button type="submit">Submit</button>

    </form>

  `

})

export class TemplateFormComponent {

  onSubmit(form: any) {

    console.log(form.value);

  }

}

 

// Example of Reactive form:

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

import { FormGroup, FormControl, Validators } from '@angular/forms';

 

@Component({

  selector: 'app-reactive-form',

  template: `

    <form [formGroup]="form" (ngSubmit)="onSubmit()">

      <input formControlName="name" required>

      <button type="submit">Submit</button>

    </form>

  `

})

export class ReactiveFormComponent implements OnInit {

  form: FormGroup;

 

  ngOnInit() {

    this.form = new FormGroup({

      name: new FormControl('', Validators.required),

    });

  }

 

  onSubmit() {

    console.log(this.form.value);

  }

}

 

// Question 6: What are Angular services and how are they used?

 

// Answer:

// Services in Angular are used to share data and logic across components. They are singleton objects, meaning there is only one instance of the service in the application. Services are typically used to encapsulate business logic, interact with external APIs, or share state between components.

 

// Example:

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

 

@Injectable({

  providedIn: 'root',

})

export class LoggerService {

  log(message: string) {

    console.log(message);

  }

}

 

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

import { LoggerService } from './logger.service';

 

@Component({

  selector: 'app-root',

  template: '<button (click)="logMessage()">Log Message</button>',

})

export class AppComponent {

  constructor(private logger: LoggerService) {}

 

  logMessage() {

    this.logger.log('Hello from AppComponent!');

  }

}

 

// Question 21: What is Module Federation in Angular?

 

// Answer:

// Module Federation is a feature introduced in Webpack 5 that allows multiple independently built and deployed applications to form a single application. It enables the sharing of code between applications at runtime, which helps in creating micro-frontends or splitting a monolithic application into smaller, manageable parts.

 

// Example:

// webpack.config.js for host application

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

 

module.exports = {

  output: {

    publicPath: 'http://localhost:3000/',

  },

  plugins: [

    new ModuleFederationPlugin({

      name: 'hostApp',

      remotes: {

        remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',

      },

      shared: ['@angular/core', '@angular/common', '@angular/router'],

    }),

  ],

};

 

// webpack.config.js for remote application

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

 

module.exports = {

  output: {

    publicPath: 'http://localhost:3001/',

  },

  plugins: [

    new ModuleFederationPlugin({

      name: 'remoteApp',

      filename: 'remoteEntry.js',

      exposes: {

        './Component': './src/app/component',

      },

      shared: ['@angular/core', '@angular/common', '@angular/router'],

    }),

  ],

};

 

// Question 22: How do you configure Module Federation in Angular?

 

// Answer:

// To configure Module Federation in Angular, you need to adjust the Webpack configuration for both the host and remote applications. Use the ModuleFederationPlugin to define the exposed modules and the shared dependencies.

 

// Example:

// angular.json modifications for custom Webpack configuration

{

  "projects": {

    "hostApp": {

      "architect": {

        "build": {

          "builder": "@angular-builders/custom-webpack:browser",

          "options": {

            "customWebpackConfig": {

              "path": "./webpack.config.js"

            }

          }

        },

        "serve": {

          "builder": "@angular-builders/custom-webpack:dev-server",

          "options": {

            "customWebpackConfig": {

              "path": "./webpack.config.js"

            }

          }

        }

      }

    }

  }

}

 

// Question 23: What are the benefits of using Module Federation?

 

// Answer:

// Benefits of using Module Federation include:

1. Independent deployment of micro-frontends.

2. Improved scalability and maintainability.

3. Sharing code between applications without duplication.

4. Reduced bundle sizes by loading only required modules.

5. Seamless updates and versioning for different parts of the application.

 

// Question 24: What are some common use cases for Module Federation?

 

// Answer:

// Common use cases for Module Federation include:

1. Micro-frontend architecture.

2. Splitting a monolithic application into smaller, independently deployable modules.

3. Sharing libraries or components across multiple applications.

4. Dynamic module loading at runtime based on user requirements.

 

// Question 25: How do you share dependencies using Module Federation?

 

// Answer:

// Shared dependencies in Module Federation are specified in the Webpack configuration under the `shared` property. This ensures that only one instance of the shared dependency is loaded, avoiding duplication and version conflicts.

 

// Example:

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

 

module.exports = {

  plugins: [

    new ModuleFederationPlugin({

      name: 'app',

      remotes: {},

      exposes: {},

      shared: {

        '@angular/core': { singleton: true, strictVersion: true, requiredVersion: 'auto' },

        '@angular/common': { singleton: true, strictVersion: true, requiredVersion: 'auto' },

      },

    }),

  ],

};

 

// Question 26: How do you expose a module using Module Federation?

 

// Answer:

// To expose a module using Module Federation, you define the module in the `exposes` property of the ModuleFederationPlugin in your Webpack configuration. This makes the module available for other applications to consume.

 

// Example:

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

 

module.exports = {

  plugins: [

    new ModuleFederationPlugin({

      name: 'remoteApp',

      filename: 'remoteEntry.js',

      exposes: {

        './Component': './src/app/component',

      },

    }),

  ],

};

 

// Question 27: How do you consume a remote module using Module Federation?

 

// Answer:

// To consume a remote module using Module Federation, you define the remote application and the module to be consumed in the `remotes` property of the ModuleFederationPlugin in your Webpack configuration. Then, you can dynamically import the module in your application code.

 

// Example:

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

 

module.exports = {

  plugins: [

    new ModuleFederationPlugin({

      name: 'hostApp',

      remotes: {

        remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',

      },

    }),

  ],

};

 

// Consuming the remote module in Angular

import { loadRemoteModule } from '@angular-architects/module-federation';

 

@NgModule({

  imports: [

    RouterModule.forRoot([

      {

        path: 'remote',

        loadChildren: () =>

          loadRemoteModule({

            remoteEntry: 'http://localhost:3001/remoteEntry.js',

            remoteName: 'remoteApp',

            exposedModule: './Component',

          }).then(m => m.RemoteComponent),

      },

    ]),

  ],

})

export class AppModule {}

 

// Question 28: How do you handle version mismatches in Module Federation?

 

// Answer:

// Version mismatches in Module Federation can be handled using the `strictVersion` and `singleton` properties in the `shared` configuration. These properties enforce specific version constraints and ensure that only one instance of the shared dependency is loaded.

 

// Example:

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');


Comments