Angular Interview Questions

1. What are lifecycle hooks available?

Angular page Lifecycle

Angular component page lifecycle are :

  1. ngOnChanges: When the value of a data bound property changes, then this method is called.
  2. ngOnInit: This is called whenever the initialization of the directive/component after Angular first displays the data-bound properties happens.
  3. ngDoCheck: This is for the detection and to act on changes that Angular can't or won't detect on its own.
  4. ngAfterContentInit: This is called in response after Angular projects external content into the component's view.
  5. ngAfterContentChecked: This is called in response after Angular checks the content projected into the component.
  6. ngAfterViewInit: This is called in response after Angular initializes the component's views and child views.
  7. ngAfterViewChecked: This is called in response after Angular checks the component's views and child views.
  8. ngOnDestroy: This is the cleanup phase just before Angular destroys the directive/component.

2. What is a data binding?

Data binding is a core concept in Angular and allows to define communication between a component and the DOM, making it very easy to define interactive applications without worrying about pushing and pulling data. There are four forms of data binding(divided as 3 categories) which differ in the way the data is flowing.
  1. From the Component to the DOM: Interpolation: {{ value }}: Adds the value of a property from the component
<li>Name: {{ }}</li>
<li>Address: {{ user.address }}</li>
Property binding: [property]=”value”: The value is passed from the component to the specified property or simple HTML attribute
<input type="email" [value]="">
  1. From the DOM to the Component: Event binding: (event)=”function”: When a specific DOM event happens (eg.: click, change, keyup), call the specified method in the component
<button (click)="logout()"></button>
  1. Two-way binding: Two-way data binding: [(ngModel)]=”value”: Two-way data binding allows to have the data flow both ways. For example, in the below code snippet, both the email DOM input and component email property are in sync
<input type="email" [(ngModel)]="">

3. What is metadata?

Metadata is used to decorate a class so that it can configure the expected behavior of the class. The metadata is represented by decorators

Class decorators, e.g. @Component and @NgModule


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

        selector: 'my-component',
        template: '<div>Class decorator</div>',
        export class MyComponent {
        constructor() {
        console.log('My Component');

        imports: [],
        declarations: [],
        export class MyModule {
        constructor() {
        console.log('My Module!');

Property decorators Used for properties inside classes, e.g. @Input and @Output


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

        selector: 'my-component',
        template: '<div>Property decorator</div>'

        export class MyComponent {
        title: string;

 Method decorators Used for methods inside classes, e.g. @HostListener


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

        selector: 'my-component',
        template: '<div>Method decorator</div>'
        export class MyComponent {
        @HostListener('click', ['$event'])
        onHostClick(event: Event) {
        // clicked, `event` available

Parameter decorators Used for parameters inside class constructors, e.g. @Inject


        import { Component, Inject } from '@angular/core';
        import { MyService } from './my-service';

        selector: 'my-component',
        template: '<div>Parameter decorator</div>'
        export class MyComponent {
        constructor(@Inject(MyService) myService) {
        console.log(myService); // MyService

4. What is a service?

A service is used when a common functionality needs to be provided to various modules. Services allow for greater separation of concerns for your application and better modularity by allowing you to extract common functionality out of components. Let's create a repoService which can be used across components,


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

        @Injectable({ // The Injectable decorator is required for dependency injection to work
        // providedIn option registers the service with a specific NgModule
        providedIn: 'root',  // This declares the service with the root app (AppModule)
        export class RepoService{
        constructor(private http: Http){

        return this.http.get('');

5. What is the purpose of async pipe?

The AsyncPipe subscribes to an observable or promise and returns the latest value it has emitted. When a new value is emitted, the pipe marks the component to be checked for changes. Let's take a time observable which continuously updates the view for every 2 seconds with the current time.


        selector: 'async-observable-pipe',
        template: `<div>
            Time: {{ time | async }}
        export class AsyncObservablePipeComponent {
        time = new Observable(observer =>
        setInterval(() => Date().toString()), 2000)

6. What is the purpose of ngFor directive?

We use Angular ngFor directive in the template to display each item in the list. For example, here we iterate over list of users,


<li *ngFor="let user of users">
        {{ user }}

7. What is the purpose of ngIf directive?

Sometimes an app needs to display a view or a portion of a view only under specific circumstances. The Angular ngIf directive inserts or removes an element based on a truthy/falsy condition. Let's take an example to display a message if the user age is more than 18,


<p *ngIf="user.age > 18">You are not eligible for student pass!</p>

8. What happens if you use script tag inside template?

Angular recognizes the value as unsafe and automatically sanitizes it, which removes the <script> tag but keeps safe content such as the text content of the <script> tag. This way it eliminates the risk of script injection attacks. If you still use it then it will be ignored and a warning appears in the browser console. Let's take an example of innerHtml property binding which causes XSS vulnerability,


        export class InnerHtmlBindingComponent {
        // For example, a user/attacker-controlled value from a URL.
        htmlSnippet = 'Template
<script>alert("0wned")</script> <b>Syntax</b>';

9. What is interpolation?

Interpolation is a special syntax that Angular converts into property binding. It’s a convenient alternative to property binding. It is represented by double curly braces {{}}. The text between the braces is often the name of a component property. Angular replaces that name with the string value of the corresponding component property. Let's take an example,

10. What are template expressions?

A template expression produces a value similar to any Javascript expression. Angular executes the expression and assigns it to a property of a binding target; the target might be an HTML element, a component, or a directive. In the property binding, a template expression appears in quotes to the right of the = symbol as in [property]="expression". In interpolation syntax, the template expression is surrounded by double curly braces. For example, in the below interpolation, the template expression is {{username}},


<h3>{{username}}, welcome to Angular</h3>

The below javascript expressions are prohibited in template expression

  1. assignments (=, +=, -=, ...)
  2. new
  3. chaining expressions with ; or ,
  4. increment and decrement operators (++ and --)

11. What are pipes?

A pipe takes in data as input and transforms it to a desired output. For example, let us take a pipe to transform a component's birthday property into a human-friendly date using date pipe.


        import { Component } from '@angular/core';
        selector: 'app-birthday',
        template: `<p>Birthday is {{ birthday | date }}</p>`
        export class BirthdayComponent {
        birthday = new Date(1987, 6, 18); // June 18, 1987

12. What is a parameterized pipe?

A pipe can accept any number of optional parameters to fine-tune its output. The parameterized pipe can be created by declaring the pipe name with a colon ( : ) and then the parameter value. If the pipe accepts multiple parameters, separate the values with colons. Let's take a birthday example with a particular format(dd/mm/yyyy):


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

        selector: 'app-birthday',
        template: `<p>Birthday is {{ birthday | date:'dd/mm/yyyy'}}</p>` // 18/06/1987
        export class BirthdayComponent {
        birthday = new Date(1987, 6, 18);

13. How do you chain pipes?

You can chain pipes together in potentially useful combinations as per the needs. Let's take a birthday property which uses date pipe(along with parameter) and uppercase pipes as below


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

        selector: 'app-birthday',
        template: `<p>Birthday is {{  birthday | date:'fullDate' | uppercase}} </p>` // THURSDAY, JUNE 18, 1987
        export class BirthdayComponent {
        birthday = new Date(1987, 6, 18);

14. What is a custom pipe?

Apart from built-inn pipes, you can write your own custom pipe with the below key characteristics,

1. A pipe is a class decorated with pipe metadata @Pipe decorator, which you import from the core Angular library For example


        @Pipe({name: 'myCustomPipe'})

2. The pipe class implements the PipeTransform interface's transform method that accepts an input value followed by optional parameters and returns the transformed value. The structure of pipeTransform would be as below



        interface PipeTransform {
        transform(value: any, ...args: any[]): any

3. The @Pipe decorator allows you to define the pipe name that you'll use within template expressions. It must be a valid JavaScript identifier.


        template: `{{someInputValue | myCustomPipe: someOtherValue}}`

15. How to create custom pipe?

You can create custom reusable pipes for the transformation of existing value. For example, let us create a custom pipe for finding file size based on an extension,


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

        @Pipe({name: 'customFileSizePipe'})
        export class FileSizePipe implements PipeTransform {
        transform(size: number, extension: string = 'MB'): string {
        return (size / (1024 * 1024)).toFixed(2) + extension;

Now you can use the above pipe in template expression as below,


        template: `
<h2>Find the size of a file</h2>
<p>Size: {{288966 | customFileSizePipe: 'GB'}}</p>

16. What is a bootstrapping module?

Every application has at least one Angular module, the root module that you bootstrap to launch the application is called as bootstrapping module. It is commonly known as AppModule. The default structure of AppModule generated by AngularCLI would be as follows,


        import { BrowserModule } from '@angular/platform-browser';
        import { NgModule } from '@angular/core';
        import { FormsModule } from '@angular/forms';
        import { HttpClientModule } from '@angular/common/http';

        import { AppComponent } from './app.component';

        /* the AppModule class with the @NgModule decorator */
        declarations: [
        imports: [
        providers: [],
        bootstrap: [AppComponent]
        export class AppModule { }

17. How can you read full response?

The response body doesn't may not return full response data because sometimes servers also return special headers or status code which which are important for the application workflow. Inorder to get full response, you should use observe option from HttpClient,


        getCustomerResponse(): Observable<HttpResponse<Cusomer>> {
  return this.http.get<Cusomer>(
    this.userUrl, { observe: 'response' });

18.What is subscribing?

An Observable instance begins publishing values only when someone subscribes to it. So you need to subscribe by calling the subscribe() method of the instance, passing an observer object to receive the notifications. Let's take an example of creating and subscribing to a simple observable, with an observer that logs the received message to the console.


        Creates an observable sequence of 5 integers, starting from 1
        const source = range(1, 5);

        // Create observer object
        const myObserver = {
        next: x => console.log('Observer got a next value: ' + x),
        error: err => console.error('Observer got an error: ' + err),
        complete: () => console.log('Observer got a complete notification'),

        // Execute with the observer object and Prints out each item
        // => Observer got a next value: 1
        // => Observer got a next value: 2
        // => Observer got a next value: 3
        // => Observer got a next value: 4
        // => Observer got a next value: 5
        // => Observer got a complete notification

19. What is an observable?

An Observable is a unique Object similar to a Promise that can help manage async code. Observables are not part of the JavaScript language so we need to rely on a popular Observable library called RxJS. The observables are created using new keyword. Let see the simple example of observable,


        import { Observable } from 'rxjs';

        const observable = new Observable(observer => {
        setTimeout(() => {'Hello from a Observable!');
        }, 2000);

20. What is an observer?

Observer is an interface for a consumer of push-based notifications delivered by an Observable. It has below structure,


        interface Observer<T>
            closed?: boolean;
            next: (value: T) => void;
            error: (err: any) => void;
            complete: () => void;

A handler that implements the Observer interface for receiving observable notifications will be passed as a parameter for observable as below,



21. What is multicasting?

Multi-casting is the practice of broadcasting to a list of multiple subscribers in a single execution. Let's demonstrate the multi-casting feature,


        var source = Rx.Observable.from([1, 2, 3]);
        var subject = new Rx.Subject();
        var multicasted = source.multicast(subject);

        // These are, under the hood, `subject.subscribe({...})`:
        next: (v) => console.log('observerA: ' + v)
        next: (v) => console.log('observerB: ' + v)

        // This is, under the hood, `s

22. How do you perform error handling in observables?

You can handle errors by specifying an error callback on the observer instead of relying on try/catch which are ineffective in asynchronous environment. For example, you can define error callback as below,


        next(num) { console.log('Next num: ' + num)},
        error(err) { console.log('Received an errror: ' + err)}

23. What is the short hand notation for subscribe method?

The subscribe() method can accept callback function definitions in line, for next, error, and complete handlers is known as short hand notation or Subscribe method with positional arguments. For example, you can define subscribe method as below,


        x => console.log('Observer got a next value: ' + x),
        err => console.error('Observer got an error: ' + err),
        () => console.log('Observer got a complete notification')

24. What are observable creation functions?

RxJS provides creation functions for the process of creating observables from things such as promises, events, timers and Ajax requests. Let us explain each of them with an example,

1. Create an observable from a promise


        import { from } from 'rxjs'; // from function
        const data = from(fetch('/api/endpoint')); //Created from Promise
        next(response) { console.log(response); },
        error(err) { console.error('Error: ' + err); },
        complete() { console.log('Completed'); }

Create an observable that creates an AJAX request


        import { ajax } from 'rxjs/ajax'; // ajax function
        const apiData = ajax('/api/data'); // Created from AJAX request
        // Subscribe to create the request
        apiData.subscribe(res => console.log(res.status, res.response));

Create an observable from a counter


        import { interval } from 'rxjs'; // interval function
        const secondsCounter = interval(1000); // Created from Counter value
        secondsCounter.subscribe(n =>
        console.log(`Counter value: ${n}`));

Create an observable from an event


        import { fromEvent } from 'rxjs';
        const el = document.getElementById('custom-element');
        const mouseMoves = fromEvent(el, 'mousemove');
        const subscription = mouseMoves.subscribe((e: MouseEvent) => {
        console.log(`Coordnitaes of mouse pointer: ${e.clientX} * ${e.clientY}`);

25. How do you define typings for custom elements?

You can use the NgElement and WithProperties types exported from @angular/elements. Let's see how it can be applied by comparing with Angular component, The simple container with input property would be as below,


        class MyContainer {
        @Input() message: string;

After applying types typescript validates input value and their types,


        const container = document.createElement('my-container') as NgElement & WithProperties<{message: string}>
            container.message = 'Welcome to Angular elements!';
            container.message = true;  // <-- ERROR: TypeScript knows this should be a string.
                                              container.greet='News' ; // <-- ERROR: TypeScript knows there is no `greet` property on `container`.