Skip to content

A quoi sert @Injectable dans Angular ?

Dans Angular, @Injectable est une décoration qui indique qu'une classe peut être utilisée comme un service injectable. Cela signifie que vous pouvez injecter une instance de cette classe dans d'autres classes de votre application, comme un composant ou un autre service.

Que se passe t-il si on n'utilise pas @Injectable ?

Si vous omettez la décoration @Injectable sur une classe qui est utilisée comme un service injectable dans votre application Angular, vous pouvez rencontrer des erreurs lors de la compilation ou de l'exécution de votre application.

Voici un exemple de déclaration d'un service sans la décoration @Injectable :

ts
import { HttpClient } from '@angular/common/http'

export class MyService {
  constructor(private http: HttpClient) {}
}
import { HttpClient } from '@angular/common/http'

export class MyService {
  constructor(private http: HttpClient) {}
}

Si vous essayez d'injecter cette instance de MyService dans un composant ou un autre service de votre application, vous pouvez obtenir l'erreur suivante lors de la compilation :

Error: Can't resolve all parameters for MyService: (?).
Error: Can't resolve all parameters for MyService: (?).

Cette erreur se produit car Angular ne peut pas résoudre les dépendances de MyService, car il ne sait pas que cette classe peut être utilisée comme un service injectable.

Pour résoudre cette erreur, vous devez ajouter la décoration @Injectable à votre classe de service pour indiquer à Angular qu'elle peut être utilisée comme un service injectable :

ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'

@Injectable({
  providedIn: 'root'
})
export class MyService {
  constructor(private http: HttpClient) {}
}
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'

@Injectable({
  providedIn: 'root'
})
export class MyService {
  constructor(private http: HttpClient) {}
}

Vous pouvez ensuite injecter cette instance de MyService dans un composant en utilisant le décorateur @Component et en la déclarant dans la liste des dépendances du constructeur du composant :

ts
import { Component } from '@angular/core';
import { MyService } from './my.service';

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponent {
  constructor(private myService: MyService) { }
}
import { Component } from '@angular/core';
import { MyService } from './my.service';

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponent {
  constructor(private myService: MyService) { }
}

Mettre dans providedIn ou dans le providers de AppModule ?

Utiliser providedIn peut être une bonne option pour améliorer les performances de votre application grâce au "tree shaking" et pour faciliter les tests unitaires.

Le "tree shaking" est une technique utilisée par les outils de build modernes pour optimiser la taille de votre application en ne conservant que le code qui est utilisé dans votre application. Si vous utilisez providedIn pour déclarer votre service, le code de votre service sera automatiquement inclus dans le build de votre application uniquement si l'instance de votre service est utilisée par un composant ou un autre service de votre application. Cela peut contribuer à réduire la taille de votre application et à améliorer ses performances.

En ce qui concerne les tests unitaires, utiliser providedIn peut rendre la configuration de vos tests unitaires plus simple et plus rapide, car vous n'avez pas à vous soucier de l'enregistrement de votre service dans un module spécifique. Vous pouvez simplement importer votre service et le déclarer dans la liste des dépendances de votre composant ou de votre service de test, comme vous le feriez normalement.

Bien que l'utilisation de providedIn puisse être avantageuse pour le "tree shaking" et les tests unitaires, cela peut ne pas être la solution idéale dans tous les cas. Vous devriez évaluer vos besoins et votre contexte de développement pour déterminer si providedIn est la bonne option pour votre application.

Utiliser providedIn

La propriété providedIn est utilisée dans la décoration @Injectable pour indiquer à Angular où enregistrer l'instance de ce service.

Voici un exemple de déclaration d'un service avec @Injectable et la propriété providedIn :

ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MyService {
  constructor() {}
}
import { Injectable } from '@angular/core';

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

Dans cet exemple, la valeur de providedIn est 'root', ce qui signifie que l'instance de MyService sera enregistrée dans le conteneur de services racine d'Angular et qu'il sera disponible pour tous les composants de votre application.

Mettre le module dans provideIn

Pour enregistrer l'instance de votre service dans un module spécifique, vous devez effectivement importer le module et le spécifier dans la propriété providedIn de la décoration @Injectable.

ts
import { Injectable } from '@angular/core';
import { MyModule } from './my.module';

@Injectable({
  providedIn: MyModule
})
export class MyService {
  constructor() {}
}
import { Injectable } from '@angular/core';
import { MyModule } from './my.module';

@Injectable({
  providedIn: MyModule
})
export class MyService {
  constructor() {}
}

Dans cet exemple, l'instance de MyService sera enregistrée dans le conteneur de services du module MyModule, ce qui signifie qu'elle ne sera disponible que pour les composants du module MyModule et de ses sous-modules.