6
votes

Détection angulaire du changement d'itinéraire uniquement lors de la navigation vers un autre composant

J'essaie de faire quelque chose lors du changement d'itinéraire (c'est-à-dire défiler vers le haut) uniquement lorsque je navigue vers un composant différent dans mon application, mais pas lorsque je reste sur le même composant et que je change simplement sa vue par une route vers le même composant query params

Par exemple, si je suis dans / products? category = kitchen et que je navigue vers / products? category = bedroom je ne veux pas l'opération (faire défiler vers le haut) pour effectuer.

Voici le code dans mon app.component.ts:

this.router.events.pipe(
  filter(event => event instanceof NavigationEnd)
).subscribe((event: NavigationEnd) => {
  // Would like to check here if user navigates to different component
  if (window) window.scrollTo(0, 0);
});

Est-ce que quelqu'un sait comment je peux ça?


2 commentaires

L'avez-vous résolu?


@MuhammadMabrouk Oui, je viens de publier la réponse


3 Réponses :


0
votes

EDIT:

Comme je ne connais pas votre cas d'utilisation, je ne peux que supposer que vous essayez d'atteindre les objectifs suivants:

Dans votre application, d'une manière ou d'une autre, le paramètre de requête "category" peut être changé, par exemple par un clic sur une catégorie. Au lieu de faire un

router.navigate (['/ products? Category =' + newSelectedCategory]);

et probablement de réagir sur ce paramètre de requête avec

import {Router, ActivatedRoute, Params} from '@angular/router';
import {OnInit, Component} from '@angular/core';

@Component({...})
export class MyComponent implements OnInit {

  category: string;

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        this.category = params['category'];
    });
  }

  // This will probably be called from your html code
  selectCategory(category: string) {
     this.category = category;
     this.location.replaceState(`products?category=${category}`);
  }
}

vous pouvez faire:

import {Router, ActivatedRoute, Params} from '@angular/router';
import {OnInit, Component} from '@angular/core';

@Component({...})
export class MyComponent implements OnInit {

  category: string;

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        this.category = params['category'];
    });
  }

}

De cette façon, il n'y aura pas de routage.


Une façon possible est de ne pas router, mais de changer l'URL actuelle avec this.location.replaceState (en supposant que vous ayez injecté private location: Location dans votre constructeur) et démarrer manuellement le même processus que celui qui se produirait lorsque vous liriez le paramètre de requête de l'URL.


3 commentaires

Je ne suis pas sûr de vous avoir compris. Pouvez-vous modifier et fournir un pseudo exemple? Merci


J'ai remplacé l'état, mais mon router.url et enabledroute ne détectent pas le changement d'état


Un changement d'état diffère d'un changement d'itinéraire. L'état est simplement un nom d'affichage. Pour notifier router.url et enabledRoute, vous devez effectuer un router.navigate vers cet emplacement.



1
votes

Vous pouvez vous abonner à la paramMap ActivatedRoute pour faire votre travail:

<router-outlet></router-outlet>

et vous assurer que la vue des catégories est une route enfant de produits code>.

Également à la place de la vue produits dans le modèle html , ajoutez un espace réservé de routage où la vue enfant sera placée:

this.activatedRoute.paramMap.subscribe(paramMap  =>  {
        this.router.navigate('your child route here');
    });

Vous pouvez en savoir plus sur le routage imbriqué ici:


2 commentaires

Merci pour la réponse suggérée, mais le problème avec elle est que cela me permettra d'exécuter du code uniquement lorsque je route vers le même composant alors que je voulais que le code s'exécute à chaque changement de route, sauf lors du routage vers le même composant. D'autres suggestions?


@yanivps avez-vous résolu le problème, j'ai aussi le même



2
votes

Je souhaite partager comment j'ai résolu ce problème au cas où quelqu'un rencontrerait quelque chose de similaire à l'avenir:

private componentBeforeNavigation = null;
  private setScrollToTopOnNavigation() {
    // Scroll to top only when navigating to a different component
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe((event: NavigationEnd) => {
      let currentRoute = this.route;
      while (currentRoute.firstChild) currentRoute = currentRoute.firstChild;
      if (this.componentBeforeNavigation !== currentRoute.component) {
        if (window) window.scrollTo(0, 0);
      }
      this.componentBeforeNavigation = currentRoute.component;
    });
  }

Ce code utilise une propriété privée pour le composant appelé componentBeforeNavigation qui est initialement null et à chaque fois que l'événement Navigation est déclenché, le code dans subscribe vérifie si l'endroit où je navigue maintenant est le même comme dernière navigation. Si oui, cela signifie que c'est une navigation vers le même composant et que je n'effectue pas mon action spéciale (dans ce cas, faites défiler vers le haut de la fenêtre) et si non, cela signifie que c'est une navigation vers un nouveau composant.
Une chose importante est de stocker le nouveau composant vers lequel je navigue dans la propriété componentBeforeNavigation afin qu'il soit toujours mis à jour avec la dernière navigation


1 commentaires

A travaillé comme un charme! Merci encore pour votre aide 😍