Passing Additional Parameters To An Angular Service
2 min read

Tags

  • Angular
  • Dependency Injection
  • Injection Token

If you want to pass additional parameters to an Angular service, what you are looking for is @Inject decorator. It helps you pass your parameters to the service through Angular’s dependency injection mechanism.

@Inject() is a manual mechanism for letting Angular know that a parameter must be injected.

-- Rangle.io

Let’s say we’re writing a recaptcha service which requires the id of the recaptcha container in your html template, as below.

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

@Injectable({
  providedIn: 'root'
})
export class RecaptchaService {
    constructor (private recaptchaContainerId: string) { }
}

Our example component:

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

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

  constructor() { }

}

How do we go about properly passing in the recaptchaContainerId to the service? Here’s how.

 

  1. We make an injection token out of the recaptchaContainerId parameter as follows:
import {Inject, Injectable} from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class RecaptchaService {
  constructor (
    // Make recaptchaContainerId an injection token
    @Inject('recaptchaContainerId') private recaptchaContainerId: string
  ) { }
}

Injection tokens are a feature of Angular that allows the injection of values that don’t have a runtime representation. What we mean by this, is that you can’t inject something like an interface as it only exists as a TypeScript construct, not JavaScript. Injection tokens provide a simple mechanism to link a token, to a value, and have that value injected into a component.

-- Inversion of Control

 

  1. We then provide this token to the service through our component’s providers array as follows:
import { Component } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `
    <div id="recaptcha-container"></div>
  `,
   providers: [
     // Provide a value to be used by Angular's dependency injection
     // machanism to pass 
    {provide: 'recaptchaContainerId', useValue: 'recaptcha-container'},
  ]
})
export class ExampleComponent {

  // We also inject our service
  constructor(private recaptchaService: RecaptchaService) { }

}

Note that I’ve deliberately limited the scope of the provided recaptchaContainerId to this component due to the nature of such a token (an element id). In another component where RecaptchaService is injected, I might be using a different id.

It’s still very ok to provide the recaptchaContainerId token in the above component’s module or the root AppModule. More here.

And that’s it! We’ve successfully passed an additional parameter to an Angular service. Found something that can be improved? Please feel free to use the comment :-).

This Stackoverflow question served as a valuable guide in writing this blog post.