Routage Angular2 avec Hashtag vers l'ancre de page

120

Je souhaite ajouter des liens sur ma page Angular2, qui, lorsque vous cliquez dessus, passeront à des positions spécifiques dans cette page, comme le font les hashtags normaux. Donc, les liens seraient quelque chose comme

/users/123#userInfo
/users/123#userPhoto
/users/123#userLikes

etc.

Je ne pense pas avoir besoin de HashLocationStrategy, car je suis d'accord avec la méthode Angular2 normale, mais si j'ajoute directement, le lien passerait en fait à la racine, pas quelque part sur la même page. Toute direction est appréciée, merci.

Calcul
la source

Réponses:

130

Mettre à jour

Ceci est maintenant pris en charge

<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});

Ajoutez le code ci-dessous à votre composant pour faire défiler

  import {ActivatedRoute} from '@angular/router'; // <-- do not forget to import

  private fragment: string;

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
  }

  ngAfterViewInit(): void {
    try {
      document.querySelector('#' + this.fragment).scrollIntoView();
    } catch (e) { }
  }

Original

Il s'agit d'un problème connu et suivi sur https://github.com/angular/angular/issues/6595

Günter Zöchbauer
la source
1
@invot une variable avec une chaîne (par exemple ce qui 123est dans la question) en supposant que le chemin de la route attend un paramètre comme{ path: 'users/:id', ....}
Günter Zöchbauer
2
Si vous voulez faire défiler jusqu'à l'ancre, voir cet article: github.com/angular/angular/issues/6595
Pere Pages
12
Remarque: cela ne défile toujours pas
Martín Coll
2
oui cela fonctionne avec setTimeout, si j'ai trouvé une meilleure solution, je vous le ferai savoir
Amr Ibrahim
1
Pour ceux qui ont du mal à faire défiler jusqu'à des identifiants de type numérique, pensez à cela 01ou à des 100sélecteurs CSS valides. Vous voudrez peut-être ajouter une lettre ou quelque chose pour en faire un sélecteur valide. Vous passeriez donc toujours 01comme un fragment, mais le iddevrait être quelque chose comme d01et donc document.querySelector('#d'+id)correspondre.
pop
52

Bien que la réponse de Günter soit correcte, elle ne couvre pas le "saut vers" la partie de la balise d'ancrage .

Par conséquent, en plus de:

<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});

... dans le composant (parent) où vous avez besoin d'un comportement "sauter à", ajoutez:

import { Router, NavigationEnd } from '@angular/router';

class MyAppComponent {
  constructor(router: Router) {

    router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = router.parseUrl(router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(true); }
        }
      }
    });

  }
}

Veuillez noter qu'il s'agit d'une solution de contournement ! Suivez ce numéro de github pour les futures mises à jour. Crédits à Victor Savkin pour avoir fourni la solution!

Kaloyan Kosev
la source
bonjour, je crée une page FAQ où vous pouvez accéder à la réponse en cliquant sur une question définie dans une liste en haut de la page. Ainsi, l'utilisateur est déjà sur la page en cours lorsqu'il saute à l'ancre. Si je veux que l'attribut routerLink fonctionne, je dois donner "['../faq']"comme valeur ou bien il essaiera de sauter à / faq / faq / # anchor, insteaf of / faq / # anchor. Est-ce la bonne façon de le faire ou existe-t-il une manière plus élégante de se référer à la page actuelle dans routerlink? En outre, document.querySelector("#" + tree.fragment);me donne une erreur de sélecteur non valide. Êtes-vous sûr que c'est exact? Merci
Maurice
2
lorsque vous cliquez à nouveau sur le même lien, cela ne fonctionne pas. Quelqu'un a-t-il fait en sorte que cela fonctionne si l'utilisateur clique sur le même lien d'ancrage <a [routerLink]="['/faq']" fragment="section6">?
Junior Mayhé
@JuniorM Avez-vous déjà compris cela? Je rencontre le même problème.
The Muffin Man
@Muffin, essayez quelque chose comme ça github.com/juniormayhe/Mailing/blob/master/Mailing.SPA/src/app/…
Junior Mayhé
1
Cela nécessite plus de visibilité. C'est une meilleure réponse IMO. La plupart des gens voudront passer à la section.
iamtravisw le
45

Désolé d'avoir répondu un peu tard; Il existe une fonction prédéfinie dans la documentation du routage angulaire qui nous aide à acheminer avec un hashtag vers l'ancre de page, c'est-à-dire anchorScrolling: 'enabled'

Étape 1: - Importez d'abord le RouterModule dans le fichier app.module.ts: -

imports:[ 
    BrowserModule, 
    FormsModule,
    RouterModule.forRoot(routes,{
      anchorScrolling: 'enabled'
    })
  ],

Étape 2: - Accédez à la page HTML, créez la navigation et ajoutez deux attributs importants tels que [routerLink] et fragment pour faire correspondre les identifiants Div respectifs : -

<ul>
    <li> <a [routerLink] = "['/']"  fragment="home"> Home </a></li>
    <li> <a [routerLink] = "['/']"  fragment="about"> About Us </a></li>
  <li> <a [routerLink] = "['/']"  fragment="contact"> Contact Us </a></li>
</ul>

Étape 3: - Créez une section / div en faisant correspondre le nom de l' ID avec le fragment : -

<section id="home" class="home-section">
      <h2>  HOME SECTION </h2>
</section>

<section id="about" class="about-section">
        <h2>  ABOUT US SECTION </h2>
</section>

<section id="contact" class="contact-section">
        <h2>  CONTACT US SECTION </h2>
</section>

Pour votre référence, j'ai ajouté l'exemple ci-dessous en créant une petite démo qui aide à résoudre votre problème.

Démo: https://routing-hashtag-page-anchors.stackblitz.io/

Naheed Shareef
la source
Merci beaucoup pour cela. Propre, concis et ça marche!
Belmiris
2
Oui, merci, pour l'auto-scoll lors du chargement de la page avec Angular 7, il suffit d'ajouter l' scrollPositionRestoration: 'enabled',option sous anchorScrolling :)
Mickaël
Cela ajoute correctement le hachage à la fin de mon url, mais il ne s'ancre pas au div du même nom. Je ne sais pas ce qui me manque. J'ai suivi les trois étapes ci-dessus.
oaklandrichie
@oaklandrichie: Pouvez-vous partager le code jsfiddle / stackblitz ici. Je peux vous aider
Naheed Shareef
cette réponse doit définitivement être acceptée, fonctionne comme du charme!
Kiss Koppány
25

Un peu tard mais voici une réponse que j'ai trouvée qui fonctionne:

<a [routerLink]="['/path']" fragment="test" (click)="onAnchorClick()">Anchor</a>

Et dans le composant:

constructor( private route: ActivatedRoute, private router: Router ) {}

  onAnchorClick ( ) {
    this.route.fragment.subscribe ( f => {
      const element = document.querySelector ( "#" + f )
      if ( element ) element.scrollIntoView ( element )
    });
  }

Ce qui précède ne fait pas défiler automatiquement jusqu'à la vue si vous arrivez sur une page avec déjà une ancre, j'ai donc utilisé la solution ci-dessus dans mon ngInit afin qu'elle puisse également fonctionner avec cela:

ngOnInit() {
    this.router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = this.router.parseUrl(this.router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(element); }
        }
      }
    });
  }

Assurez-vous d'importer Router, ActivatedRoute et NavigationEnd au début de votre composant et tout devrait être prêt.

La source

Ali Bari
la source
4
Travaille pour moi! Si vous souhaitez naviguer dans la même page que vous êtes déjà sur, utilisez [routerLink] = "['.']"
Raoul
1
pourriez-vous expliquer davantage? cette partie document.querySelector ( "#" + f )me donne une erreur car elle attend un sélecteur, pas une chaîne.
Maurice
1
@Maurice pour moi cela fonctionne: element.scrollIntoView()(sans passer elementà la fonction). Pour le rendre lisse, utilisez ceci: element.scrollIntoView({block: "end", behavior: "smooth"}).
Mr. B.
IntelliSense ici montre que dans les onAnchorClick(), il faut passer un booléen à scrollIntoView: if (element) { element.scrollIntoView(true); }. Maintenant je peux cliquer deux fois sur le même lien et faire défiler les oeuvres
Junior Mayhé
18

Aucune des réponses précédentes n'a fonctionné pour moi. Dans un dernier effort, j'ai essayé dans mon modèle:

<a (click)="onClick()">From Here</a>
<div id='foobar'>To Here</div>

Avec ceci dans mes .ts:

onClick(){
    let x = document.querySelector("#foobar");
    if (x){
        x.scrollIntoView();
    }
}

Et cela fonctionne comme prévu pour les liens internes. Cela n'utilise pas réellement de balises d'ancrage, donc cela ne toucherait pas du tout l'URL.

Wenqin Chen
la source
1
simple et facile
WasiF
6

Les solutions ci-dessus n'ont pas fonctionné pour moi ... Celui-ci l'a fait:

Tout d'abord, préparez-vous MyAppComponentau défilement automatique dans ngAfterViewChecked () ...

import { Component, OnInit, AfterViewChecked } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

@Component( {
   [...]
} )
export class MyAppComponent implements OnInit, AfterViewChecked {

  private scrollExecuted: boolean = false;

  constructor( private activatedRoute: ActivatedRoute ) {}

  ngAfterViewChecked() {

    if ( !this.scrollExecuted ) {
      let routeFragmentSubscription: Subscription;

      // Automatic scroll
      routeFragmentSubscription =
        this.activatedRoute.fragment
          .subscribe( fragment => {
            if ( fragment ) {
              let element = document.getElementById( fragment );
              if ( element ) {
                element.scrollIntoView();

                this.scrollExecuted = true;

                // Free resources
                setTimeout(
                  () => {
                    console.log( 'routeFragmentSubscription unsubscribe' );
                    routeFragmentSubscription.unsubscribe();
                }, 1000 );

              }
            }
          } );
    }

  }

}

Ensuite, accédez à l' my-app-routeenvoi du prodIDhashtag

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component( {
   [...]
} )
export class MyOtherComponent {

  constructor( private router: Router ) {}

  gotoHashtag( prodID: string ) {
    this.router.navigate( [ '/my-app-route' ], { fragment: prodID } );
  }

}
JavierFuentes
la source
Voter sans commentaires ni explications ... ce n'est pas une bonne pratique ...
JavierFuentes
Cela a fonctionné pour moi! Pourquoi utiliser ngAfterViewChecked au lieu de ngInit?
Antoine Boisier-Michaud
Merci @ AntoineBoisier-Michaud pour vos retours positifs. ngInit ne se déclenche pas toujours dont j'ai besoin dans mon projet ... ngAfterViewChecked le fait. Pouvez-vous voter pour cette solution s'il vous plaît? Merci.
JavierFuentes
6

Toutes les autres réponses fonctionneront sur la version Angular <6.1. Mais si vous avez la dernière version, vous n'aurez pas besoin de faire ces horribles hacks car Angular a résolu le problème.

voici le lien vers le problème

Tout ce que vous avez à faire est de définir scrollOffsetl'option du deuxième argument de RouterModule.forRootméthode.

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled',
      anchorScrolling: 'enabled',
      scrollOffset: [0, 64] // [x, y]
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}
आनंद
la source
2
cela fonctionnera-t-il pour les liens extérieurs? dire à partir d'un autre site Web, je clique sur www.abc.com # sectionToScrollTo
Sushmit Sagar
anchorScrolling ne fonctionne pas, si vous faites un usage intensif de * ngIf, car il saute au début :-(
Jojo.Lechelt
Le seul problème que j'ai eu avec cela est le timing - il a tendance à sauter à l'ancre avant que le style de certains éléments n'ait atteint le rendu complet, provoquant un positionnement désactivé. Ce serait bien si vous pouviez ajouter un délai :)
Charly
5

Utilisez ceci pour le module de routeur dans app-routing.module.ts:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    useHash: true,
    scrollPositionRestoration: 'enabled',
    anchorScrolling: 'enabled',
    scrollOffset: [0, 64]
  })],
  exports: [RouterModule]
})

Ce sera dans votre HTML:

<a href="#/users/123#userInfo">
razak faizal
la source
4

Dans un fichier html:

<a [fragment]="test1" [routerLink]="['./']">Go to Test 1 section</a>

<section id="test1">...</section>
<section id="test2">...</section>

Dans le fichier ts:

export class PageComponent implements AfterViewInit, OnDestroy {

  private destroy$$ = new Subject();
  private fragment$$ = new BehaviorSubject<string | null>(null);
  private fragment$ = this.fragment$$.asObservable();

  constructor(private route: ActivatedRoute) {
    this.route.fragment.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
      this.fragment$$.next(fragment);
    });
  }

  public ngAfterViewInit(): void {
    this.fragment$.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
      if (!!fragment) {
        document.querySelector('#' + fragment).scrollIntoView();
      }
    });
  }

  public ngOnDestroy(): void {
    this.destroy$$.next();
    this.destroy$$.complete();
  }
}
Sebastian Schulze-Khyi
la source
Le querySelector pourrait facilement être placé dans une directive nommée scrolllTo. L'URL serait <a scrollTo="test1" [routerLink </font>="['./'ITED"> Aller à la section Test 1 </a>
John Peters
3

Étant donné que la propriété de fragment ne fournit toujours pas de défilement d'ancrage, cette solution de contournement a fait l'affaire pour moi:

<div [routerLink]="['somepath']" fragment="Test">
  <a href="#Test">Jump to 'Test' anchor </a>
</div>
Martin Cremer
la source
3

En plus de la réponse de Kalyoyan , cet abonnement est lié au routeur et restera en ligne jusqu'à ce que la page soit complètement actualisée. Lorsque vous vous abonnez aux événements du routeur dans un composant, assurez-vous de vous désabonner dans ngOnDestroy:

import { OnDestroy } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Subscription } from "rxjs/Rx";

class MyAppComponent implements OnDestroy {

  private subscription: Subscription;

  constructor(router: Router) {
    this.subscription = router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = router.parseUrl(router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(element); }
        }
      }
    });
  }

  public ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}
DBosley
la source
Je pensais que les abonnements aux événements d'itinéraire étaient automatiquement supprimés.
3

Je viens de le faire fonctionner sur mon propre site Web, alors j'ai pensé que cela valait la peine de publier ma solution ici.

<a [routerLink]="baseUrlGoesHere" fragment="nameOfYourAnchorGoesHere">Link Text!</a>

<a name="nameOfYourAnchorGoesHere"></a>
<div>They're trying to anchor to me!</div>

Et puis dans votre composant, assurez-vous d'inclure ceci:

 import { ActivatedRoute } from '@angular/router';

 constructor(private route: ActivatedRoute) { 
     this.route.fragment.subscribe ( f => {
         const element = document.querySelector ( "#" + f )
         if ( element ) element.scrollIntoView ( element )
     });
 }
un_lovelace
la source
Je pense qu'il vaut mieux écrire juste element.scrollIntoView()ou element.scrollIntoView(true). Votre version ne s'est pas compilée pour moi (peut-être à cause de strictNullChecks?).
David L.
3

Après avoir lu toutes les solutions, j'ai cherché un composant et j'en ai trouvé un qui fait exactement ce que la question initiale demandait: faire défiler pour ancrer les liens. https://www.npmjs.com/package/ng2-scroll-to

Lorsque vous l'installez, vous utilisez une syntaxe telle que:

// app.awesome.component.ts
@Component({
   ...
   template: `...
        <a scrollTo href="#main-section">Scroll to main section</a>
        <button scrollTo scrollTargetSelector="#test-section">Scroll to test section</a>
        <button scrollTo scrollableElementSelector="#container" scrollYTarget="0">Go top</a>
        <!-- Further content here -->
        <div id="container">
            <section id="main-section">Bla bla bla</section>
            <section id="test-section">Bla bla bla</section>
        <div>
   ...`,
})
export class AwesomeComponent {
}

Cela a très bien fonctionné pour moi.

John
la source
Utilisez la roue, ne l'inventez plus;)
Yogen Rai
Avez-vous regardé le code derrière ce composant? Il semble très fragile - le projet a également 14 problèmes ouverts - qui incluent des éléments tels que l'élément non existant, les cibles nulles, ne pas défiler jusqu'à l'élément, les problèmes de support du navigateur.
Drenai
ne fonctionne pas lorsque vous avez un enfant (l'enfant a des entités ancrées et / ou des noms d'ancrage) dans le composant parent, il actualise simplement la page
Sasha Bond
3

Une solution simple qui fonctionne pour les pages sans aucun paramètre de requête, est compatible avec le navigateur en arrière / en avant, le routeur et les liens profonds.

<a (click)="jumpToId('anchor1')">Go To Anchor 1</a>


ngOnInit() {

    // If your page is dynamic
    this.yourService.getWhatever()
        .then(
            data => {
            this.componentData = data;
            setTimeout(() => this.jumpToId( window.location.hash.substr(1) ), 100);
        }
    );

    // If your page is static
    // this.jumpToId( window.location.hash.substr(1) )
}

jumpToId( fragment ) {

    // Use the browser to navigate
    window.location.hash = fragment;

    // But also scroll when routing / deep-linking to dynamic page
    // or re-clicking same anchor
    if (fragment) {
        const element = document.querySelector('#' + fragment);
        if (element) element.scrollIntoView();
    }
}

Le délai d'attente est simplement de permettre à la page de charger toutes les données dynamiques «protégées» par un * ngIf. Cela peut également être utilisé pour faire défiler vers le haut de la page lors du changement d'itinéraire - il suffit de fournir une balise d'ancrage supérieure par défaut.

Graham Hotchkiss
la source
2

si cela n'a pas d'importance d'avoir ces identifiants d'élément ajoutés à l'URL, vous devriez envisager de jeter un œil à ce lien:

Angulaire 2 - Liens d'ancrage vers l'élément sur la page actuelle

// html
// add (click) event on element
<a (click)="scroll({{any-element-id}})">Scroll</a>

// in ts file, do this
scroll(sectionId) {
let element = document.getElementById(sectionId);

  if(element) {
    element.scrollIntoView(); // scroll to a particular element
  }
 }

Ramu N
la source
1

Voici une autre solution de contournement avec référence à la réponse JavierFuentes:

<a [routerLink]="['self-route', id]" fragment="some-element" (click)="gotoHashtag('some-element')">Jump to Element</a>

dans le script:

import {ActivatedRoute} from "@angular/router";
import {Subscription} from "rxjs/Subscription";

export class Links {
    private scrollExecuted: boolean = false;

    constructor(private route: ActivatedRoute) {} 

    ngAfterViewChecked() {
            if (!this.scrollExecuted) {
              let routeFragmentSubscription: Subscription;
              routeFragmentSubscription = this.route.fragment.subscribe(fragment => {
                if (fragment) {
                  let element = document.getElementById(fragment);
                  if (element) {
                    element.scrollIntoView();
                    this.scrollExecuted = true;
                    // Free resources
                    setTimeout(
                      () => {
                        console.log('routeFragmentSubscription unsubscribe');
                        routeFragmentSubscription.unsubscribe();
                      }, 0);
                  }
                }
              });
            }
          }

        gotoHashtag(fragment: string) {
            const element = document.querySelector("#" + fragment);
            if (element) element.scrollIntoView(element);
        }
}

Cela permet à l'utilisateur de faire défiler directement jusqu'à l'élément, si l'utilisateur atterrit directement sur la page ayant le hashtag dans l'url.

Mais dans ce cas, je me suis abonné à la route Fragment in ngAfterViewCheckedmais ngAfterViewChecked()est appelée en continu pour chaque ngDoChecket cela ne permet pas à l'utilisateur de faire défiler vers le haut, doncrouteFragmentSubscription.unsubscribe est appelée après un délai d'expiration de 0 millis après le défilement de la vue jusqu'à l'élément.

De plus, une gotoHashtagméthode est définie pour faire défiler jusqu'à l'élément lorsque l'utilisateur clique spécifiquement sur la balise d'ancrage.

Mettre à jour:

Si l'url a des chaînes de requêtes, [routerLink]="['self-route', id]"dans anchor ne conservera pas les chaînes de requêtes. J'ai essayé la solution de contournement suivante pour le même:

<a (click)="gotoHashtag('some-element')">Jump to Element</a>

constructor( private route: ActivatedRoute,
              private _router:Router) {
}
...
...

gotoHashtag(fragment: string) {
    let url = '';
    let urlWithSegments = this._router.url.split('#');

    if(urlWithSegments.length){
      url = urlWithSegments[0];
    }

    window.location.hash = fragment;
    const element = document.querySelector("#" + fragment);
    if (element) element.scrollIntoView(element);
}
Vicky Gonsalves
la source
1

Celui-ci fonctionne pour moi !! Ce ngPour qu'il ancre dynamiquement la balise, vous devez attendre leur rendu

HTML:

<div #ngForComments *ngFor="let cm of Comments">
    <a id="Comment_{{cm.id}}" fragment="Comment_{{cm.id}}" (click)="jumpToId()">{{cm.namae}} Reply</a> Blah Blah
</div>

Mon fichier ts:

private fragment: string;
@ViewChildren('ngForComments') AnchorComments: QueryList<any>;

ngOnInit() {
      this.route.fragment.subscribe(fragment => { this.fragment = fragment; 
   });
}
ngAfterViewInit() {
    this.AnchorComments.changes.subscribe(t => {
      this.ngForRendred();
    })
}

ngForRendred() {
    this.jumpToId()
}

jumpToId() { 
    let x = document.querySelector("#" + this.fragment);
    console.log(x)
    if (x){
        x.scrollIntoView();
    }
}

N'oubliez pas d'importer ça ViewChildren, QueryListetc. et ajoutez un constructeur ActivatedRoute!!

John Connor
la source
1

Contrairement à d' autres réponses que je voudrais en outre ajouter aussi focus()avec scrollIntoView(). J'utilise aussi setTimeoutcar il saute en haut sinon lors du changement d'URL. Je ne sais pas quelle était la raison de cela, mais il semble setTimeoutque la solution de contournement.

Origine:

<a [routerLink] fragment="some-id" (click)="scrollIntoView('some-id')">Jump</a>

Destination:

<a id="some-id" tabindex="-1"></a>

Manuscrit:

scrollIntoView(anchorHash) {
    setTimeout(() => {
        const anchor = document.getElementById(anchorHash);
        if (anchor) {
            anchor.focus();
            anchor.scrollIntoView();
        }
    });
}
Hrvoje Golcic
la source
1

J'ai eu le même problème. La solution: utiliser View Port Scroller https://angular.io/api/common/ViewportScroller#scrolltoanchor

- code app-routing.module.ts:

import { PageComponent } from './page/page.component';

const routes: Routes = [
   path: 'page', component: PageComponent },
   path: 'page/:id', component: PageComponent }
];

- HTML du composant

  <a (click) = "scrollTo('typeExec')">
    <mat-icon>lens</mat-icon>
  </a>

- Code du composant:

    import { Component } from '@angular/core';
    import { ViewportScroller } from '@angular/common';


    export class ParametrageComponent {

      constructor(private viewScroller: ViewportScroller) {}

      scrollTo(tag : string)
      {
        this.viewScroller.scrollToAnchor(tag);
      }

    }
Abderrahim Taleb
la source
0

Je viens de tester un plugin très utile disponible dans nmp - ngx-scroll-to , qui fonctionne très bien pour moi. Cependant, il est conçu pour Angular 4+, mais peut-être que quelqu'un trouvera cette réponse utile.

mpro
la source
0

J'ai essayé la plupart de ces solutions mais j'ai rencontré des problèmes de départ et de retour avec un autre fragment qui ne fonctionnait pas, alors j'ai fait quelque chose d'un peu différent qui fonctionne à 100% et me débarrasse du hachage laid dans l'URL.

tl; dr voici un meilleur moyen que ce que j'ai vu jusqu'à présent.

import { Component, OnInit, AfterViewChecked, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

@Component({
    selector: 'app-hero',
    templateUrl: './hero.component.html',
    styleUrls: ['./hero.component.scss']
})
export class HeroComponent implements OnInit, AfterViewChecked, OnDestroy {
    private fragment: string;
    fragSub: Subscription;

    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        this.fragSub = this.route.fragment.subscribe( fragment => { this.fragment = fragment; })
    }

    ngAfterViewChecked(): void {
        try {
            document.querySelector('#' + this.fragment).scrollIntoView({behavior: 'smooth'});
            window.location.hash = "";
          } catch (e) { }
    }

    ngOnDestroy() {
        this.fragSub.unsubscribe();
    }
}
Kyle S
la source