Ajouter la fonctionnalité de recherche à votre application

Cette leçon du tutoriel montre comment ajouter une fonctionnalité de recherche à votre application Angular.

L'application permettra aux utilisateurs de rechercher parmi les données fournies par votre application et de n'afficher que les résultats correspondant au terme saisi.

Important : Nous vous recommandons d'utiliser votre environnement local pour cette étape du tutoriel.

Ce que vous allez apprendre

  • Votre application utilisera les données d'un formulaire pour rechercher les logements correspondants
  • Votre application n'affichera que les logements correspondants
  1. Modifier les propriétés du composant home

    Dans cette étape, vous allez modifier la classe Home pour stocker des données dans une nouvelle propriété de type tableau que vous utiliserez pour le filtrage.

    1. Dans src/app/home/home.ts, ajoutez à la classe une nouvelle propriété nommée filteredLocationList.

      Ajouter la propriété filteredLocationList dans home.ts

      import {ChangeDetectorRef, 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" #filter />
              <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of filteredLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        private readonly changeDetectorRef = inject(ChangeDetectorRef);
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
        filteredLocationList: HousingLocationInfo[] = [];
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
          this.filteredLocationList = this.housingLocationList;
        }
      
        filterResults(text: string) {
          if (!text) {
            this.filteredLocationList = this.housingLocationList;
            return;
          }
      
          this.filteredLocationList = this.housingLocationList.filter((housingLocation) =>
            housingLocation?.city.toLowerCase().includes(text.toLowerCase()),
          );
        }
      }

      filteredLocationList contient les valeurs qui correspondent aux critères de recherche saisis par l'utilisateur.

    2. Par défaut, au chargement de la page, filteredLocationList doit contenir l'ensemble des logements. Modifiez le constructor de Home pour définir cette valeur.

      Définir la valeur de filteredLocationList

      import {ChangeDetectorRef, 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" #filter />
              <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of filteredLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        private readonly changeDetectorRef = inject(ChangeDetectorRef);
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
        filteredLocationList: HousingLocationInfo[] = [];
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
          this.filteredLocationList = this.housingLocationList;
        }
      
        filterResults(text: string) {
          if (!text) {
            this.filteredLocationList = this.housingLocationList;
            return;
          }
      
          this.filteredLocationList = this.housingLocationList.filter((housingLocation) =>
            housingLocation?.city.toLowerCase().includes(text.toLowerCase()),
          );
        }
      }
  2. Modifier le template du composant home

    Home contient déjà un champ de saisie que vous utiliserez pour capturer la saisie de l'utilisateur. Ce texte servira à filtrer les résultats.

    1. Modifiez le template de Home pour inclure une variable de template nommée #filter dans l'élément input.

      Ajouter une variable de template à l'élément HTML input dans home.ts

      import {ChangeDetectorRef, 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" #filter />
              <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of filteredLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        private readonly changeDetectorRef = inject(ChangeDetectorRef);
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
        filteredLocationList: HousingLocationInfo[] = [];
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
          this.filteredLocationList = this.housingLocationList;
        }
      
        filterResults(text: string) {
          if (!text) {
            this.filteredLocationList = this.housingLocationList;
            return;
          }
      
          this.filteredLocationList = this.housingLocationList.filter((housingLocation) =>
            housingLocation?.city.toLowerCase().includes(text.toLowerCase()),
          );
        }
      }

      Cet exemple utilise une variable de référence de template pour accéder à l'élément input et à sa valeur.

    2. Ensuite, modifiez le template du composant pour attacher un event handler au bouton « Search ».

      Lier l'événement click du bouton à une méthode dans home.ts

      import {ChangeDetectorRef, 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" #filter />
              <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of filteredLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        private readonly changeDetectorRef = inject(ChangeDetectorRef);
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
        filteredLocationList: HousingLocationInfo[] = [];
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
          this.filteredLocationList = this.housingLocationList;
        }
      
        filterResults(text: string) {
          if (!text) {
            this.filteredLocationList = this.housingLocationList;
            return;
          }
      
          this.filteredLocationList = this.housingLocationList.filter((housingLocation) =>
            housingLocation?.city.toLowerCase().includes(text.toLowerCase()),
          );
        }
      }

      En vous liant à l'événement click de l'élément button, vous pouvez appeler la fonction filterResults. L'argument de la fonction est la propriété value de la variable de template filter, c'est-à-dire la propriété .value de l'élément HTML input.

    3. La dernière modification du template concerne la directive @for. Modifiez le @for pour qu'il itère sur les valeurs du tableau filteredLocationList.

      Modifier la directive de template @for dans home.ts

      import {ChangeDetectorRef, 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" #filter />
              <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of filteredLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        private readonly changeDetectorRef = inject(ChangeDetectorRef);
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
        filteredLocationList: HousingLocationInfo[] = [];
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
          this.filteredLocationList = this.housingLocationList;
        }
      
        filterResults(text: string) {
          if (!text) {
            this.filteredLocationList = this.housingLocationList;
            return;
          }
      
          this.filteredLocationList = this.housingLocationList.filter((housingLocation) =>
            housingLocation?.city.toLowerCase().includes(text.toLowerCase()),
          );
        }
      }
  3. Implémenter la fonction de l'event handler

    Le template a été modifié pour lier la fonction filterResults à l'événement click. Votre tâche consiste maintenant à implémenter la fonction filterResults dans la classe Home.

    1. Modifiez la classe Home pour inclure l'implémentation de la fonction filterResults.

      Ajouter l'implémentation de la fonction filterResults

      import {ChangeDetectorRef, 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" #filter />
              <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button>
            </form>
          </section>
          <section class="results">
            @for (housingLocation of filteredLocationList; track $index) {
              <app-housing-location [housingLocation]="housingLocation" />
            }
          </section>
        `,
        styleUrls: ['./home.css'],
      })
      export class Home {
        private readonly changeDetectorRef = inject(ChangeDetectorRef);
        housingLocationList: HousingLocationInfo[] = [];
        housingService: HousingService = inject(HousingService);
        filteredLocationList: HousingLocationInfo[] = [];
      
        constructor() {
          this.housingLocationList = this.housingService.getAllHousingLocations();
          this.filteredLocationList = this.housingLocationList;
        }
      
        filterResults(text: string) {
          if (!text) {
            this.filteredLocationList = this.housingLocationList;
            return;
          }
      
          this.filteredLocationList = this.housingLocationList.filter((housingLocation) =>
            housingLocation?.city.toLowerCase().includes(text.toLowerCase()),
          );
        }
      }

      Cette fonction utilise la fonction filter de Array pour comparer la valeur du paramètre text à la propriété housingLocation.city. À titre d'exercice ludique, vous pouvez modifier cette fonction pour qu'elle compare n'importe quelle propriété ou plusieurs propriétés.

    2. Enregistrez votre code.

    3. Actualisez le navigateur et vérifiez que vous pouvez rechercher les logements par ville lorsque vous cliquez sur le bouton « Search » après avoir saisi du texte.

      résultats de recherche filtrés selon la saisie de l'utilisateur

Résumé : Dans cette leçon, vous avez modifié votre application pour utiliser des variables de template afin d'interagir avec les valeurs du template, et ajouté une fonctionnalité de recherche à l'aide de l'event binding et de fonctions de tableau.

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