Référence : https://angular.io/tutorial/first-app/first-app-lesson-10

Le routage est la possibilité de naviguer d'un composant de l'application à un autre. Dans les applications à page unique (Single Page Application), seules certaines parties de la page sont mises à jour pour représenter la vue demandée pour l'utilisateur.

Le routeur Angular permet aux utilisateurs de déclarer des routes et de spécifier quel composant doit être affiché à l'écran si cette route est demandée par l'application.

Création d'un nouveau composant "Détails"

Ce composant permettra d'afficher les "détails" d'une location

ng generate component details --standalone --inline-template --skip-tests

Mise en place des routes

Dans le répertoire src/app, créer un fichier appelé routes.ts. C'est dans ce fichier que l'on va définir les routes de notre application.

Dans main.ts, appliquer les modifications suivantes pour activer le "routing" :

import { bootstrapApplication,provideProtractorTestingSupport } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { provideRouter } from '@angular/router';
import routeConfig from './app/routes';

bootstrapApplication(AppComponent,
  {
    providers: [
      provideProtractorTestingSupport(),
      provideRouter(routeConfig)
    ]
  }
).catch(err => console.error(err));

Mise à jour du component app

Dans src/app/app.component.ts, mettrre à jour le composant pour utiliser le "routing" :

import { Component, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
  <main>
    <a [routerLink]="['/']">
      <header class="brand-name">
        <img class="brand-logo" src="/assets/logo.svg" alt="logo" aria-hidden="true">
      </header>
    </a>
    <section class="content">
      <router-outlet></router-outlet>
    </section>
  </main>
`,
  styleUrls: ['./app.component.css'],
  imports: [HomeComponent, RouterModule],
})
export class AppComponent {
  title = 'my-first-project';
}

 

Ajout d'une route au nouveau composant 

Dans routes.ts, coller le code suivant :

import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { DetailsComponent } from './details/details.component';

const routeConfig: Routes = [
  {
    path: '',
    component: HomeComponent,
    title: 'Home page'
  },
  {
    path: 'details/:id',
    component: DetailsComponent,
    title: 'Home details'
  }
];
export default routeConfig;

Les entrées du tableau routeConfig représentent les routes dans l'application. La première entrée accède au HomeComponent chaque fois que l'URL correspond à ''. La deuxième entrée utilise une mise en forme spéciale qui sera expliquée très prochainement.

Vérifier que votre application afficher toujours les différentes maisons.

Intégrer la page de détails dans l'application

Dans src/app/housing-location/housing-location.component.ts, ajouter une balise d'ancrage à l'élément section et inclure la directive routerLink :

import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HousingLocation } from '../housinglocation';
import { RouterModule } from '@angular/router';

@Component({
  selector: 'app-housing-location',
  standalone: true,
  imports: [CommonModule, RouterModule],
  template: `
    <section class="listing">
      <img
        class="listing-photo"
        [src]="housingLocation.photo"
        alt="Exterior photo of {{ housingLocation.name }}"
      />
      <h2 class="listing-heading">{{ housingLocation.name }}</h2>
      <p class="listing-location">
        {{ housingLocation.city }}, {{ housingLocation.state }}
      </p>
      <a [routerLink]="['/details', housingLocation.id]">Learn More</a>
    </section>
  `,
  styleUrls: ['./housing-location.component.css'],
})
export class HousingLocationComponent {
  @Input() housingLocation!: HousingLocation;
}

A cette étape, le clic sur "learn more" doit faire apparaître le texte "details works"

Récupérer les paramètres de route

Dans src/app/details/details.component.ts mettre à jour le template pour importer les fonctions, classes et services dont nous avons besoin : 

import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { HousingService } from '../housing.service';
import { HousingLocation } from '../housinglocation';


Mettre à jour le decorateur @Component pour afficher la valeur de  housingLocationId:

template: `<p>details works! {{ housingLocationId }}</p>`,

Mettre à jour le corps de DetailsComponent avec le code suivant :

export class DetailsComponent {
    route: ActivatedRoute = inject(ActivatedRoute);
    housingLocationId = -1;
    constructor() {
        this.housingLocationId = Number(this.route.snapshot.params['id']);
    }
}

Ce code donne au DetailsComponent l'accès à la fonction de routeur ActivatedRoute qui vous permet d'avoir accès aux données concernant la route actuelle. Dans le constructeur, le code convertit le paramètre id de la route en un nombre.

Enregistrer toutes les modifications et vérifier que votre code fonctionne en cliquant sur "Learn more", vous devriez voir apparaitre l'identifiant de la location.

Personnaliser le Component Details

Maintenant que le routage fonctionne correctement dans l'application, c'est le moment de mettre à jour le template afin d'afficher les données spécifiques du logement.

Modifier le fichier src/app/details/details.component.ts avec le code suivant :

import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { HousingService } from '../housing.service';
import { HousingLocation } from '../housinglocation';

@Component({
  selector: 'app-details',
  standalone: true,
  imports: [CommonModule],
  template: `
    <article>
      <img
        class="listing-photo"
        [src]="housingLocation?.photo"
        alt="Exterior photo of {{ housingLocation?.name }}"
      />
      <section class="listing-description">
        <h2 class="listing-heading">{{ housingLocation?.name }}</h2>
        <p class="listing-location">
          {{ housingLocation?.city }}, {{ housingLocation?.state }}
        </p>
      </section>
      <section class="listing-features">
        <h2 class="section-heading">About this housing location</h2>
        <ul>
          <li>Units available: {{ housingLocation?.availableUnits }}</li>
          <li>Does this location have wifi: {{ housingLocation?.wifi }}</li>
          <li>
            Does this location have laundry: {{ housingLocation?.laundry }}
          </li>
        </ul>
      </section>
    </article>
  `,
  styleUrls: ['./details.component.css'],
})
export class DetailsComponent {
  route: ActivatedRoute = inject(ActivatedRoute);
  housingService = inject(HousingService);
  housingLocation: HousingLocation | undefined;

  constructor() {
    const housingLocationId = Number(this.route.snapshot.params['id']);
    this.housingLocation =
      this.housingService.getHousingLocationById(housingLocationId);
  }
}

Vous remarquerez que les changements concernent le template et la déclaration de la classe avec le constructeur qui définit la variable housingLocationId et qui assigne une valeur issue du service à la propriété housingService.

Mise en page 

Pour finir, ajouter le code suivant dans le fichier details.component.css : 

.listing {
  background: var(--accent-color);
  border-radius: 30px;
  padding-bottom: 30px;
}
.listing-heading {
  color: var(--primary-color);
  padding: 10px 20px 0 0;
}
.listing-photo {
  height: 250px;
  width: 100%;
  object-fit: cover;
  border-radius: 30px 30px 0 0;
}
.listing-location {
  padding: 10px 20px 20px 0;
}
.listing-location::before {
  content: url("/assets/location-pin.svg") / "";
  position: relative;
  top: 5px;
}

section.listing a {
  padding-left: 20px;
  text-decoration: none;
  color: var(--primary-color);
}
section.listing a::after {
  content: "\203A";
  margin-left: 5px;
}
section.listing-features ul > li {
    margin-left: 25px;
}

Au final, l'interface des détails d'une location devrait ressembler à cela :

détails d'une location