Angular 10 Constructor Parameters with Inject and Optional Decorators

Angular 10 Constructor Parameters with Inject and Optional Decorators

In this example, we'll learn how to use component's and service's constructors with Angular 10 and previous versions.

We'll see how to provide dependencies as constructor parameters to components or services and use the @Optional and @Inject decorators for adding optional dependencies or create injection tokens to pass parameters to services.

As a prerequisite, you need to have Angular CLI v10 installed on your development machine.

You can also use the online Stackblitz IDE if you don't have a development environment ready yet.

Creating a New Angular 10 Project

Let's get started with a new project. Go to a new command-line interface and run the following command to create a new project:

$ ng new Angular10Constructor 

The CLI will ask you a couple of questions — If Would you like to add Angular routing? Type y for Yes and Which stylesheet format would you like to use? Choose CSS.

Next, go to you project’s folder and run the server using the following commands:

$ cd Angular10Constructor
$ ng serve    

Use your web browser and visit the http://localhost:4200/ address to see your app running.

Open your web browser and navigate to the http://localhost:4200/ address to see your app running.

What is a Constructor?

The constructor is a method in a TypeScript class that gets called when the class is being instantiated. It’s not an Angular feature but rather a concept that's present in most Object-Oriented languages including TypeScript.

This is an example:

class Cls {
  constructor() {
    console.log('Hello world!');
  }
}

const cls = new Cls();

When we instantiate the class using the new keyword, the constructor will be called.

Constructors in Angular 10

In Angular 10 and previous versions, the constructor has a special use besides its typical use. Since Angular uses dependency injection for wiring various artifacts such as components and services, the injector makes use of the constructor to inject the dependencies into the class which can a component, or a service, etc. Angular resolves providers you declare in your constructor. This is an example:

import { Component } from '@angular/core';
import { HttpClient } from "@angular/common/http";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {

  constructor(private httpClient: HttpClient) {}
}

This will provide HttpClient to the component's class, making it available to the component via this.httpClient.

In order for AppComponent to send HTTP requests, it needs to ask for HttpClient to be injected, rather than creating its own HttpClient instance with new.

You can tell Angular to inject a dependency in a component's constructor by specifying a constructor parameter with the dependency type. Here's the AppComponent constructor, asking for the HttpClient to be injected:

constructor(private httpClient: HttpClient) {}

Passing Optional Dependencies

When a component or service needs a dependency, the class constructor takes that dependency as a parameter. You can tell Angular that the dependency is optional by annotating the constructor parameter with @Optional().

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

constructor(@Optional() private httpClient?: HttpClient) {

Passing Parameters to Services with the @Inject Decorator

If you need to pass additional parameters to an Angular service, you can use the @Inject decorator which allows you to pass your parameters to the service via Angular’s dependency injection.

Let’s suppose we have an Angular 10 service that requires the ID of the DOM container in the component's template. For example:

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

@Injectable({
  providedIn: 'root'
})
export class MyService {
    constructor (private elementId: string) { }
}

This is an example component that can make use of this service:

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

@Component({
  selector: 'app-my',
  template: `
    <div id="container"></div>
  `,
})
export class MyComponent {

  constructor() { }

}

Now we need to inject the previous service via the component's constructor but we also need to pass the ID as a parameter to the service.

We transform the elementId parameter to an injection token as follows:

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

@Injectable({
  providedIn: 'root'
})
export class MyService {
  constructor (
    @Inject('elementId') private elementId: string
  ) { }
}

Next, we need to provide this token to the service through the component’s providers array:

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

@Component({
  selector: 'app-my',
  template: `
    <div id="container"></div>
  `,
   providers: [

    {provide: 'elementId', useValue: 'container'},
  ]
})
export class MyComponent {

  constructor(private myService: MyService) { }
}

Here we provided the token at the component level but we can also provide tokens at the module level if it makes sense.

Conclusion

We learned about using class constructors in Angular for dependency injection bu declaring providers as parameters.

We've seen how to provide dependencies as constructor parameters to components or services and use the @Optional and @Inject decorators for adding optional dependencies or create injection tokens to pass parameters to services.


  • Date: