📢 Je vous présente le livre Angular

  • 1) Il offre un contenu clair et concis, tout en couvrant une multitude de concepts d'Angular.
  • 2) Le livre est structuré en trois niveaux : débutant, intermédiaire et avancé
  • 3) traite des pratiques les plus récentes d'Angular, comme les signaux, les vues différées, la gestion des flux, entre autres
  • 4) De plus, vous y trouverez plusieurs liens vers des exemples de code source pour approfondir vos connaissances en pratique.
Consulter un extrait

Skip to content

Injection de dépendances et la fonction inject()

Quel est le but (théorie)

L'injection de dépendances (DI) est un modèle de conception logicielle qui permet de supprimer les dépendances codées en dur dans notre application.

L'injection de dépendances est utilisée pour passer une instance d'une classe à un objet dépendant. Par exemple, si nous avons une variable, par exemple client, dans notre composant, Angular se chargera de fournir un objet client réel au composant.

Angular utilise une classe appelée Injector pour faire du DI. Injector est une instance singleton dont le travail consiste à créer des instances de classes. L'injecteur utilise un ensemble de règles pour répondre à la demande de dépendance.

Savoir utiliser la fonction inject()

L'instruction inject dans Angular permet d'injecter des dépendances dans des fonctions, ce qui offre une manière alternative d'injecter des dépendances par rapport à la méthode traditionnelle basée sur les classes. Cette fonctionnalité peut s'avérer utile dans diverses situations.

Avantages

  1. Réutilisabilité L'utilisation de inject facilite le partage de code entre les composants. C'est un avantage significatif, car cela permet d'écrire des fonctions qui peuvent être utilisées dans plusieurs composants sans avoir à injecter les mêmes dépendances à chaque fois. C'est particulièrement avantageux lorsque de nombreux composants utilisent les mêmes dépendances.

  2. Inférence de type Auparavant, lorsqu'on créait une classe utilisant un token d'injection, il fallait définir explicitement le type de la propriété qui contiendrait la valeur injectée. Ce n'est plus nécessaire avec inject, car le type de la valeur injectée est déduit du type du token d'injection.

  3. Héritage dans Angular avec des dépendances injectées

    Étendre les composants, directives et autres dans Angular à partir d'autres classes a toujours été assez délicat, en particulier lorsque nous utilisons des dépendances injectées. Le problème réside dans le fait qu'avec l'injection par le constructeur, nous devons passer les dépendances au constructeur parent. Cela nécessite d'écrire du code répétitif et devient de plus en plus complexe à mesure que la chaîne d'héritage s'allonge.

    Exemple :

    Prenons deux services ServiceA et ServiceB que nous souhaitons injecter dans des classes héritées.

    typescript
    @Injectable()
    export class ServiceA { /* ... */ }
    
    @Injectable()
    export class ServiceB { /* ... */ }

    Imaginons maintenant que nous ayons une classe BaseComponent qui nécessite ServiceA, et une classe DerivedComponent qui hérite de BaseComponent et nécessite à la fois ServiceA et ServiceB.

    typescript
    export class BaseComponent {
        constructor(protected serviceA: ServiceA) { /* ... */ }
    }
    
    export class DerivedComponent extends BaseComponent {
        constructor(serviceA: ServiceA, private serviceB: ServiceB) {
            super(serviceA);
            // Le reste du code...
        }
    }

    Comme le montre cet exemple, même si DerivedComponent hérite de BaseComponent, nous devons réinjecter ServiceA dans DerivedComponent et le passer au constructeur parent via super(serviceA). Cette répétitivité et cette complexité peuvent rapidement augmenter à mesure que nous ajoutons plus de classes dans la chaîne d'héritage ou plus de dépendances injectées.

    La fonction inject peut aider à simplifier ce scénario en permettant l'injection de dépendances directement dans les fonctions et les méthodes sans avoir besoin de passer par les constructeurs, rendant ainsi l'héritage plus maniable dans Angular.

Inconvénient

Disponibilitéinject est uniquement disponible dans les contextes d'injection de dépendances. Par conséquent, son utilisation dans des classes de modèle ou DTO entraînerait des erreurs.

Exemple: Tester un Guard

Utilisation de la fonction inject()

Voici comment vous pouvez utiliser la fonction inject pour injecter un UserService dans un composant Angular :

typescript
import { Component, OnInit } from '@angular/core';
import { User } from "src/app/core/interfaces/user";
import { UserService } from 'src/app/core/services/user.service';
import { inject } from '@angular/core';

@Component({
  selector: 'app-users',
  standalone: true,
  template: `
    <div>
      Nombre d'utilisateurs : {{ users().length }}
    </div>
  `
})
export class UserComponent implements OnInit {
  private userService = inject(UserService);
  users = this.userService.users;

  // Utilisez la fonction inject pour obtenir une instance de UserService
  ngOnInit() {
    this.userService.getAll().subscribe();
  }
}
ts
import { HttpClient } from "@angular/common/http";
import { Injectable, inject, signal } from "@angular/core";
import { Observable, tap } from "rxjs";
import { User } from "../interfaces/user";

@Injectable({
  providedIn: "root",
})
export class UserService {
  private http = inject(HttpClient);
  readonly url: string = "https://jsonplaceholder.typicode.com/users";
  users = signal<User[]>([]);

  getAll(): Observable<User[]> {
    return this.http.get<User[]>(this.url).pipe(
      tap((users) => {
        this.users.set(users);
      })
    );
  }
}
ts
export interface User {
    id: number;
    name: string;
    username?: string;
    email: string;
    address?: {
        street: string;
        suite: string;
        city: string;
        zipcode: string;
        geo: {
            lat: string;
            lng: string;
        }
    };
    phone?: string;
    website?: string;
    company?: {
        name: string;
        catchPhrase: string;
        bs: string;
    };
}

Notez que nous avons directement injecté le UserService à l'aide de inject sans avoir besoin de le faire via le constructeur. Cela peut rendre votre code plus concis et offre une alternative à l'injection classique basée sur le constructeur.

Chaque mois, recevez en avant-première notre newsletter avec les dernières actualités, tutoriels, astuces et ressources Angular directement par email !