Les services Angular

Cette leçon du tutoriel montre comment créer un service Angular et utiliser l'injection de dépendances pour l'inclure dans votre application.

Ce que vous allez apprendre

Votre application dispose d'un service qui lui fournit ses données. À la fin de cette leçon, le service lit des données locales et statiques. Dans une leçon ultérieure, vous modifierez le service pour qu'il récupère les données depuis un service web.

Aperçu conceptuel des services

Ce tutoriel présente les services Angular et l'injection de dépendances.

Les services Angular

Les services Angular vous permettent de séparer les données et les fonctions de l'application Angular qui peuvent être utilisées par plusieurs composants de votre application. Pour être utilisé par plusieurs composants, un service doit être rendu injectable. Les services injectables utilisés par un composant deviennent des dépendances de ce composant. Le composant dépend de ces services et ne peut pas fonctionner sans eux.

L'injection de dépendances

L'injection de dépendances est le mécanisme qui gère les dépendances des composants d'une application et les services que d'autres composants peuvent utiliser.

  1. Créer un nouveau service pour votre application

    Cette étape crée un service injectable pour votre application.

    Dans le panneau Terminal de votre IDE :

    1. Dans le répertoire de votre projet, placez-vous dans le répertoire first-app.

    2. Dans le répertoire first-app, exécutez cette commande pour créer le nouveau service.

      ng generate service housing --skip-tests
    3. Exécutez ng serve pour compiler l'application et la servir sur http://localhost:4200.

    4. Vérifiez que l'application se compile sans erreur. Corrigez les éventuelles erreurs avant de passer à l'étape suivante.

  2. Ajouter des données statiques au nouveau service

    Cette étape ajoute quelques données d'exemple à votre nouveau service. Dans une leçon ultérieure, vous remplacerez les données statiques par une interface web pour récupérer les données comme vous le feriez dans une vraie application. Pour l'instant, le nouveau service de votre application utilise les données créées jusqu'ici localement dans Home.

    Dans le panneau Edit de votre IDE :

    1. Dans src/app/home/home.ts, copiez depuis Home la variable baseUrl et la variable housingLocationList avec son tableau de valeurs.

    2. Dans src/app/housing.service.ts :

      1. Dans la classe HousingService, collez les variables que vous avez copiées depuis Home à l'étape précédente.

      2. Dans la classe HousingService, collez ces fonctions après les données que vous venez de copier. Ces fonctions permettent aux dépendances d'accéder aux données du service.

        Fonctions du service dans src/app/housing.service.ts

        import {Service} from '@angular/core';
        import {HousingLocationInfo} from './housinglocation';
        @Service()
        export class HousingService {
          readonly baseUrl = 'https://angular.dev/assets/images/tutorials/common';
        
          protected housingLocationList: HousingLocationInfo[] = [
            {
              id: 0,
              name: 'Acme Fresh Start Housing',
              city: 'Chicago',
              state: 'IL',
              photo: `${this.baseUrl}/bernard-hermant-CLKGGwIBTaY-unsplash.jpg`,
              availableUnits: 4,
              wifi: true,
              laundry: true,
            },
            {
              id: 1,
              name: 'A113 Transitional Housing',
              city: 'Santa Monica',
              state: 'CA',
              photo: `${this.baseUrl}/brandon-griggs-wR11KBaB86U-unsplash.jpg`,
              availableUnits: 0,
              wifi: false,
              laundry: true,
            },
            {
              id: 2,
              name: 'Warm Beds Housing Support',
              city: 'Juneau',
              state: 'AK',
              photo: `${this.baseUrl}/i-do-nothing-but-love-lAyXdl1-Wmc-unsplash.jpg`,
              availableUnits: 1,
              wifi: false,
              laundry: false,
            },
            {
              id: 3,
              name: 'Homesteady Housing',
              city: 'Chicago',
              state: 'IL',
              photo: `${this.baseUrl}/ian-macdonald-W8z6aiwfi1E-unsplash.jpg`,
              availableUnits: 1,
              wifi: true,
              laundry: false,
            },
            {
              id: 4,
              name: 'Happy Homes Group',
              city: 'Gary',
              state: 'IN',
              photo: `${this.baseUrl}/krzysztof-hepner-978RAXoXnH4-unsplash.jpg`,
              availableUnits: 1,
              wifi: true,
              laundry: false,
            },
            {
              id: 5,
              name: 'Hopeful Apartment Group',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/r-architecture-JvQ0Q5IkeMM-unsplash.jpg`,
              availableUnits: 2,
              wifi: true,
              laundry: true,
            },
            {
              id: 6,
              name: 'Seriously Safe Towns',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/phil-hearing-IYfp2Ixe9nM-unsplash.jpg`,
              availableUnits: 5,
              wifi: true,
              laundry: true,
            },
            {
              id: 7,
              name: 'Hopeful Housing Solutions',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/r-architecture-GGupkreKwxA-unsplash.jpg`,
              availableUnits: 2,
              wifi: true,
              laundry: true,
            },
            {
              id: 8,
              name: 'Seriously Safe Towns',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/saru-robert-9rP3mxf8qWI-unsplash.jpg`,
              availableUnits: 10,
              wifi: false,
              laundry: false,
            },
            {
              id: 9,
              name: 'Capital Safe Towns',
              city: 'Portland',
              state: 'OR',
              photo: `${this.baseUrl}/webaliser-_TPTXZd9mOo-unsplash.jpg`,
              availableUnits: 6,
              wifi: true,
              laundry: true,
            },
          ];
        
          getAllHousingLocations(): HousingLocationInfo[] {
            return this.housingLocationList;
          }
        
          getHousingLocationById(id: number): HousingLocationInfo | undefined {
            return this.housingLocationList.find((housingLocation) => housingLocation.id === id);
          }
        }

        Vous aurez besoin de ces fonctions dans une prochaine leçon. Pour l'instant, il suffit de comprendre que ces fonctions renvoient soit un HousingLocation précis selon son id, soit la liste complète.

      3. Ajoutez un import au niveau du fichier pour HousingLocation.

        Importer le type HousingLocation dans src/app/housing.service.ts

        import {Service} from '@angular/core';
        import {HousingLocationInfo} from './housinglocation';
        @Service()
        export class HousingService {
          readonly baseUrl = 'https://angular.dev/assets/images/tutorials/common';
        
          protected housingLocationList: HousingLocationInfo[] = [
            {
              id: 0,
              name: 'Acme Fresh Start Housing',
              city: 'Chicago',
              state: 'IL',
              photo: `${this.baseUrl}/bernard-hermant-CLKGGwIBTaY-unsplash.jpg`,
              availableUnits: 4,
              wifi: true,
              laundry: true,
            },
            {
              id: 1,
              name: 'A113 Transitional Housing',
              city: 'Santa Monica',
              state: 'CA',
              photo: `${this.baseUrl}/brandon-griggs-wR11KBaB86U-unsplash.jpg`,
              availableUnits: 0,
              wifi: false,
              laundry: true,
            },
            {
              id: 2,
              name: 'Warm Beds Housing Support',
              city: 'Juneau',
              state: 'AK',
              photo: `${this.baseUrl}/i-do-nothing-but-love-lAyXdl1-Wmc-unsplash.jpg`,
              availableUnits: 1,
              wifi: false,
              laundry: false,
            },
            {
              id: 3,
              name: 'Homesteady Housing',
              city: 'Chicago',
              state: 'IL',
              photo: `${this.baseUrl}/ian-macdonald-W8z6aiwfi1E-unsplash.jpg`,
              availableUnits: 1,
              wifi: true,
              laundry: false,
            },
            {
              id: 4,
              name: 'Happy Homes Group',
              city: 'Gary',
              state: 'IN',
              photo: `${this.baseUrl}/krzysztof-hepner-978RAXoXnH4-unsplash.jpg`,
              availableUnits: 1,
              wifi: true,
              laundry: false,
            },
            {
              id: 5,
              name: 'Hopeful Apartment Group',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/r-architecture-JvQ0Q5IkeMM-unsplash.jpg`,
              availableUnits: 2,
              wifi: true,
              laundry: true,
            },
            {
              id: 6,
              name: 'Seriously Safe Towns',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/phil-hearing-IYfp2Ixe9nM-unsplash.jpg`,
              availableUnits: 5,
              wifi: true,
              laundry: true,
            },
            {
              id: 7,
              name: 'Hopeful Housing Solutions',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/r-architecture-GGupkreKwxA-unsplash.jpg`,
              availableUnits: 2,
              wifi: true,
              laundry: true,
            },
            {
              id: 8,
              name: 'Seriously Safe Towns',
              city: 'Oakland',
              state: 'CA',
              photo: `${this.baseUrl}/saru-robert-9rP3mxf8qWI-unsplash.jpg`,
              availableUnits: 10,
              wifi: false,
              laundry: false,
            },
            {
              id: 9,
              name: 'Capital Safe Towns',
              city: 'Portland',
              state: 'OR',
              photo: `${this.baseUrl}/webaliser-_TPTXZd9mOo-unsplash.jpg`,
              availableUnits: 6,
              wifi: true,
              laundry: true,
            },
          ];
        
          getAllHousingLocations(): HousingLocationInfo[] {
            return this.housingLocationList;
          }
        
          getHousingLocationById(id: number): HousingLocationInfo | undefined {
            return this.housingLocationList.find((housingLocation) => housingLocation.id === id);
          }
        }
    3. Vérifiez que l'application se compile sans erreur. Corrigez les éventuelles erreurs avant de passer à l'étape suivante.

  3. Injecter le nouveau service dans Home

    Cette étape injecte le nouveau service dans le Home de votre application pour qu'il puisse lire les données de l'application depuis un service. Dans une leçon ultérieure, vous remplacerez les données statiques par une source de données réelle pour récupérer les données comme vous le feriez dans une vraie application.

    Dans le panneau Edit de votre IDE, dans src/app/home/home.ts :

    1. En haut de src/app/home/home.ts, ajoutez inject aux éléments importés depuis @angular/core. Cela importera la fonction inject dans la classe Home.

      Modification de src/app/home/home.ts

      import {Component, inject} from '@angular/core';
      import {HousingLocation} from '../housing-location/housing-location';
      import {HousingLocationInfo} from '../housinglocation';
      import {HousingService} from '../housing.service';
      @Component({
        selector: 'app-home',
        imports: [HousingLocation],
        template: `
          <section>
            <form>
              <input type="text" placeholder="Filter by city" />
              <button class="primary" type="button">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of housingLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
        }
      }
    2. Ajoutez un nouvel import au niveau du fichier pour HousingService :

      Ajouter l'import dans src/app/home/home.ts

      import {Component, inject} from '@angular/core';
      import {HousingLocation} from '../housing-location/housing-location';
      import {HousingLocationInfo} from '../housinglocation';
      import {HousingService} from '../housing.service';
      @Component({
        selector: 'app-home',
        imports: [HousingLocation],
        template: `
          <section>
            <form>
              <input type="text" placeholder="Filter by city" />
              <button class="primary" type="button">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of housingLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
        }
      }
    3. Dans Home, supprimez la variable baseUrl, supprimez les entrées du tableau housingLocationList et affectez à housingLocationList un tableau vide ([]). Dans quelques étapes, vous modifierez le code pour récupérer les données depuis HousingService.

    4. Dans Home, ajoutez le code suivant pour injecter le nouveau service et initialiser les données de l'application. Le constructor est la première fonction exécutée à la création de ce composant. Le code du constructor affectera à housingLocationList la valeur renvoyée par l'appel à getAllHousingLocations.

      Initialiser les données depuis le service dans src/app/home/home.ts

      import {Component, inject} from '@angular/core';
      import {HousingLocation} from '../housing-location/housing-location';
      import {HousingLocationInfo} from '../housinglocation';
      import {HousingService} from '../housing.service';
      @Component({
        selector: 'app-home',
        imports: [HousingLocation],
        template: `
          <section>
            <form>
              <input type="text" placeholder="Filter by city" />
              <button class="primary" type="button">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of housingLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
        }
      }
    5. Enregistrez les modifications de src/app/home/home.ts et vérifiez que votre application se compile sans erreur. Corrigez les éventuelles erreurs avant de passer à l'étape suivante.

Résumé : Dans cette leçon, vous avez ajouté un service Angular à votre application et l'avez injecté dans la classe Home. Cela isole la manière dont votre application obtient ses données. Pour l'instant, le nouveau service obtient ses données à partir d'un tableau de données statique. Dans une leçon ultérieure, vous refactoriserez le service pour qu'il obtienne ses données depuis un endpoint d'API.

Pour plus d'informations sur les sujets abordés dans cette leçon, consultez :