Appearance
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
Navigation dans l'historique
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
Analytics et suivi utilisateur
- Suivre le parcours de l'utilisateur dans l'application
- Collecter des statistiques de navigation
- Détecter les patterns de navigation
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
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
Nom | Paramètres | Retour | Description | Cas d'usage |
---|---|---|---|---|
back() | - | void | Navigue en arrière dans l'historique | Pour implémenter un bouton "retour" personnalisé |
forward() | - | void | Navigue en avant dans l'historique | Pour implémenter un bouton "suivant" personnalisé |
getBaseHrefFromDOM() | - | string | Récupère la base href depuis la balise <base> du DOM | Pour obtenir le chemin de base de l'application |
getState() | - | unknown | Retourne l'état actuel de l'historique | Pour accéder aux données stockées dans l'état de navigation |
go() | path: string, query?: string, state?: any | void | Change l'URL du navigateur et ajoute une nouvelle entrée dans l'historique | Pour naviguer vers une nouvelle URL tout en conservant l'historique |
historyGo() | relativePosition?: number | void | Navigue à une position spécifique dans l'historique | Pour sauter plusieurs pages en avant/arrière |
isCurrentPathEqualTo() | path: string, query?: string | boolean | Compare le chemin donné avec le chemin actuel | Pour vérifier si l'utilisateur est sur une URL spécifique |
normalize() | url: string | string | Normalise un chemin URL en retirant les slashes finaux | Pour nettoyer et standardiser les URLs |
onUrlChange() | fn: (url: string, state: unknown) => void | VoidFunction | Enregistre un écouteur de changement d'URL | Pour réagir aux changements d'URL, même ceux non détectés par popstate |
path() | includeHash?: boolean | string | Retourne le chemin URL normalisé actuel | Pour obtenir l'URL courante, par exemple pour l'analyser ou la logger |
prepareExternalUrl() | url: string | string | Prépare une URL pour un usage externe en ajoutant la base href | Pour générer des URLs complètes incluant le chemin de base |
replaceState() | path: string, query?: string, state?: any | void | Change l'URL sans ajouter d'entrée dans l'historique | Pour mettre à jour l'URL sans polluer l'historique (ex: filtres) |
subscribe() | onNext: (value: PopStateEvent) => void, onThrow?: ((error: any) => void), onReturn?: (() => void)) | Subscription | Souscrit aux événements PopState du navigateur | Pour 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.