Skip to content

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

Le service Location dans Angular

Le service Location est un outil puissant fourni par Angular qui permet d'interagir avec l'URL du navigateur et de gérer l'historique de navigation. Imaginons que vous souhaitez créer un bouton "Retour" personnalisé dans votre application de gestion d'utilisateurs, ou que vous voulez modifier l'URL sans recharger toute la page - c'est exactement là que le service Location entre en jeu.

Comprendre le concept

Prenons un exemple de la vie quotidienne : lorsque vous naviguez sur un site e-commerce, vous utilisez les boutons "Précédent" et "Suivant" de votre navigateur pour parcourir les différentes pages de produits. Le service Location fonctionne de manière similaire, mais vous donne un contrôle programmatique sur ces actions.

Mise en place

Commençons par voir comment implémenter le service Location dans notre application de gestion d'utilisateurs.

ts
import { Component, inject } from '@angular/core';
import { Location } from '@angular/common';
import { User } from './user.interface';

@Component({
  standalone: true,
  selector: 'app-user-detail',
  template: `
    @if (user) {
      <div>
        <h2>{{ user.name }}</h2>
        <button (click)="goBack()">Retour</button>
      </div>
    }
  `
})
export class UserDetailComponent {
  private location = inject(Location);
  user: User | null = null;

  goBack(): void {
    this.location.back();
  }
}

Principales fonctionnalités

ts
// Reculer d'une page
this.location.back();

// Avancer d'une page
this.location.forward();

// Naviguer à une position spécifique dans l'historique
this.location.historyGo(-2); // Recule de 2 pages

Manipulation de l'URL

ts
import { Injectable, inject } from '@angular/core';
import { Location } from '@angular/common';

@Injectable({
  providedIn: 'root'
})
export class NavigationService {
  private location = inject(Location);

  updateUrl(userId: string): void {
    // Modifie l'URL sans recharger la page
    this.location.go(`/users/${userId}`);
  }

  replaceCurrentUrl(userId: string): void {
    // Remplace l'URL actuelle dans l'historique
    this.location.replaceState(`/users/${userId}`);
  }
}

Écoute des changements d'URL

ts
export class UserTrackingComponent {
  private location = inject(Location);

  ngOnInit() {
    this.location.onUrlChange((url, state) => {
      console.log(`Nouvelle URL : ${url}`, state);
    });
  }
}

Attention

Le service Location ne doit pas remplacer le Router d'Angular pour la navigation principale de votre application. Utilisez-le pour des cas spécifiques comme la gestion de l'historique ou des modifications d'URL sans rechargement.

Voici pourquoi :

  • Le Router d'Angular offre des fonctionnalités plus avancées comme :
    • La gestion des guards pour protéger les routes
    • Le chargement paresseux des modules
    • La résolution de données avant le chargement
    • La gestion des paramètres de route typés
    • Les animations de transition entre routes
  • Le service Location est conçu comme un outil complémentaire pour des manipulations bas niveau de l'URL et de l'historique
  • Utiliser uniquement Location pourrait vous faire perdre tous les avantages du système de routage d'Angular

Utilisation avancée de subscribe()

La méthode subscribe() est particulièrement utile pour suivre les changements d'état de navigation dans votre application. Elle vous permet de réagir aux événements PopState du navigateur, qui se produisent lorsque l'utilisateur navigue dans l'historique (par exemple en utilisant les boutons précédent/suivant du navigateur).

ts
import { Injectable, inject } from '@angular/core';
import { Location } from '@angular/common';

@Injectable({
  providedIn: 'root'
})
export class NavigationTrackerService {
  private location = inject(Location);

  trackNavigationChanges(): void {
    this.location.subscribe(
      // Fonction appelée à chaque changement d'état
      (event: PopStateEvent) => {
        console.log('Navigation détectée :', {
          url: this.location.path(),
          state: event.state,
          timestamp: new Date()
        });
        
        // Exemple : sauvegarder l'historique de navigation
        this.saveNavigationHistory();
      },
      // Gestion des erreurs (optionnel)
      (error) => {
        console.error('Erreur de navigation :', error);
      },
      // Fonction appelée lors du désabonnement (optionnel)
      () => {
        console.log('Suivi de navigation terminé');
      }
    );
  }

  private saveNavigationHistory(): void {
    // Logique pour sauvegarder l'historique
  }
}

Cas d'utilisation courants

  1. Analytics et suivi utilisateur

    • Suivre le parcours de l'utilisateur dans l'application
    • Collecter des statistiques de navigation
    • Détecter les patterns de navigation
  2. Synchronisation d'état

    • Mettre à jour l'interface utilisateur en fonction des changements d'URL
    • Synchroniser des données avec le serveur lors des changements de navigation
    • Gérer les états de formulaires lors de la navigation
  3. Gestion de cache

    • Invalider ou mettre à jour le cache lors des changements de navigation
    • Précharger des données en fonction de la navigation

Bonne pratique

N'oubliez pas de vous désabonner de la souscription lorsque vous n'en avez plus besoin, particulièrement dans les composants, pour éviter les fuites de mémoire :

ts
// ...
export class NavigationComponent implements OnDestroy {
  private subscription!: Subscription;
  private location = inject(Location);
  constructor() {
    this.subscription = this.location.subscribe(/* ... */);
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

Référence complète des méthodes

NomParamètresRetourDescriptionCas d'usage
back()-voidNavigue en arrière dans l'historiquePour implémenter un bouton "retour" personnalisé
forward()-voidNavigue en avant dans l'historiquePour implémenter un bouton "suivant" personnalisé
getBaseHrefFromDOM()-stringRécupère la base href depuis la balise <base> du DOMPour obtenir le chemin de base de l'application
getState()-unknownRetourne l'état actuel de l'historiquePour accéder aux données stockées dans l'état de navigation
go()path: string, query?: string, state?: anyvoidChange l'URL du navigateur et ajoute une nouvelle entrée dans l'historiquePour naviguer vers une nouvelle URL tout en conservant l'historique
historyGo()relativePosition?: numbervoidNavigue à une position spécifique dans l'historiquePour sauter plusieurs pages en avant/arrière
isCurrentPathEqualTo()path: string, query?: stringbooleanCompare le chemin donné avec le chemin actuelPour vérifier si l'utilisateur est sur une URL spécifique
normalize()url: stringstringNormalise un chemin URL en retirant les slashes finauxPour nettoyer et standardiser les URLs
onUrlChange()fn: (url: string, state: unknown) => voidVoidFunctionEnregistre un écouteur de changement d'URLPour réagir aux changements d'URL, même ceux non détectés par popstate
path()includeHash?: booleanstringRetourne le chemin URL normalisé actuelPour obtenir l'URL courante, par exemple pour l'analyser ou la logger
prepareExternalUrl()url: stringstringPrépare une URL pour un usage externe en ajoutant la base hrefPour générer des URLs complètes incluant le chemin de base
replaceState()path: string, query?: string, state?: anyvoidChange l'URL sans ajouter d'entrée dans l'historiquePour mettre à jour l'URL sans polluer l'historique (ex: filtres)
subscribe()onNext: (value: PopStateEvent) => void, onThrow?: ((error: any) => void), onReturn?: (() => void))SubscriptionSouscrit aux événements PopState du navigateurPour réagir aux changements d'état de l'historique du navigateur

À savoir

Les méthodes les plus couramment utilisées sont back(), forward(), go(), replaceState() et path(). Les autres méthodes sont généralement utilisées pour des cas plus spécifiques ou avancés.