DEV Community

Cover image for Using the Inject Function in Angular 15
Dany Paredes
Dany Paredes

Posted on • Originally published at danywalls.com

Using the Inject Function in Angular 15

Since Angular 14/15, there has been an alternative way to inject dependencies in our Angular applications.

I will show two cases to use the inject function with Angular 14/15.

Inject Dependencies in Functions

Now, using inject, we can create functions and inject dependencies without adding parameters in the function class.

Example: We create a function that needs the HttpClient to request data.

import {lastValueFrom, map} from "rxjs";
import {inject} from "@angular/core";
import {HttpClient} from "@angular/common/http";

export function getPlayers(): Promise<unknown> {
  return lastValueFrom(inject(HttpClient).get('https://www.balldontlie.io/api/v1/players').pipe(
    map((response: any) => {
      return response.data;
    })
  ))
}
Enter fullscreen mode Exit fullscreen mode

We can use the function in another class in the constructor lifecycle:

  constructor() {
    getPlayers().then(p => {
      this.players = p;
    })
  }
Enter fullscreen mode Exit fullscreen mode

The inject() function must be called from an injection context such as a constructor, a factory function, or a field initializer.

Simplify Inheritance Dependencies

Another way to simplify and clean up the constructor in our classes is when we use inheritance. For example, when a class works as a base or superclass for others, like NbaService, which needs HttpClient in the constructor.

import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {map, Observable} from 'rxjs';

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

  constructor(private http: HttpClient) {

  }

  getPlayers(): Observable<any> {
    return this.http.get('https://www.balldontlie.io/api/v1/players').pipe(
      map((response: any) => {
        return response.data;
      })
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

When we create a new class like NcaaService and extend NbaService, we must provide the constructor dependencies.

import {Injectable} from '@angular/core';
import {NbaService} from "./nba.service";
import {HttpClient} from "@angular/common/http";
import {filter} from 'rxjs';

@Injectable()
export class NcaaService extends NbaService {
  constructor(private httpClient: HttpClient) {
    super(httpClient);
  }

  getListPlayers() {
    return this.getPlayers().pipe(
      filter((p) => p.league === 'NCAA')
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

What happens if the NbaService constructor changes?

export class NbaService {
  constructor(private http: HttpClient, private loader: LoaderService) {
  }
    ....
Enter fullscreen mode Exit fullscreen mode

The NcaaService has to update the constructor and provide a dependency no related with him.

error

The easy way to solve this is to switch our dependencies from constructor to inject function.


export class NbaService {

  http = inject(HttpClient);
  loader = inject(LoaderService)

  showLoadingMessage() {
    this.loader.show();
  }
Enter fullscreen mode Exit fullscreen mode

The extended classes don't have to provide dependencies anymore. This helps to simplify our code and solve a typical problem when we have to provide dependencies without needing to, only because our base code needs it.

@Injectable()
export class NcaaService extends NbaService {
  constructor() {
    super();
  }
Enter fullscreen mode Exit fullscreen mode

Conclusion

Using the inject function in Angular applications can simplify the code and help to solve common problems related to dependency injection. With inject, we can create functions and inject dependencies without adding parameters in the function class, and we can simplify inheritance dependencies.

Latest comments (0)