Angular2 Routing mit Hashtag zum Seitenanker


120

Ich möchte meiner Angular2-Seite einige Links hinzufügen, die beim Klicken zu bestimmten Positionen innerhalb dieser Seite springen , wie dies bei normalen Hashtags der Fall ist . Die Links wären also so etwas wie

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

etc.

Ich glaube nicht, dass ich HashLocationStrategy brauche, da ich mit der normalen Angular2-Methode einverstanden bin, aber wenn ich direkt hinzufüge, würde der Link tatsächlich zum Stamm springen, nicht irgendwo auf derselben Seite. Jede Richtung wird geschätzt, danke.

Antworten:


130

Aktualisieren

Dies wird jetzt unterstützt

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

Fügen Sie Ihrer Komponente den folgenden Code hinzu, um einen Bildlauf durchzuführen

  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

Dies ist ein bekanntes Problem, das unter https://github.com/angular/angular/issues/6595 nachverfolgt werden kann


1
@invot eine Variable mit einer Zeichenfolge (zum Beispiel, was 123in der Frage ist) unter der Annahme, dass der Routenpfad einen Parameter wie{ path: 'users/:id', ....}
Günter Zöchbauer

2
Wenn Sie zum Anker scrollen möchten, lesen Sie diesen Beitrag: github.com/angular/angular/issues/6595
Pere Pages

12
Hinweis: Dies
Martín Coll

2
Ja, es funktioniert mit SetTimeout. Wenn ich eine bessere Lösung gefunden habe, werde ich es Sie wissen lassen
Amr Ibrahim

1
Für diejenigen kämpfen , um Blättern zu zahlen wie IDs, Geist, die 01oder 100nicht gültig CSS - Selektoren sind. Möglicherweise möchten Sie einen Buchstaben oder etwas hinzufügen, um ihn zu einem gültigen Selektor zu machen. Sie würden also immer noch 01als Fragment durchgehen, aber das idmüsste so etwas sein d01und document.querySelector('#d'+id)würde somit übereinstimmen.
Pop

52

Obwohl Günters Antwort richtig ist, deckt sie nicht den "Sprung zum" Anker-Tag-Teil ab .

Daher zusätzlich zu:

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

... fügen Sie in der Komponente (übergeordnet), in der Sie ein "Sprung zu" -Verhalten benötigen, Folgendes hinzu:

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); }
        }
      }
    });

  }
}

Bitte beachten Sie, dass dies eine Problemumgehung ist ! Befolgen Sie dieses Github-Problem für zukünftige Updates. Dank an Victor Savkin für die Bereitstellung der Lösung!


Hallo, ich erstelle eine FAQ-Seite, auf der Sie zur Antwort springen können, indem Sie auf eine Frage klicken, die in einer Liste oben auf der Seite definiert ist. Der Benutzer befindet sich also bereits auf der aktuellen Seite, wenn er zum Anker springt. Wenn das routerLink-Attribut funktionieren soll, muss ich es "['../faq']"als Wert angeben, sonst wird versucht, zu / faq / faq / # anchor zu springen, insteaf von / faq / # anchor. Ist dies der richtige Weg, oder gibt es einen eleganteren Weg, auf die aktuelle Seite in Routerlink zu verweisen? Auch document.querySelector("#" + tree.fragment);gibt mir keine gültigen Selektor Fehler. Sind Sie sicher, dass dies korrekt ist? Vielen Dank
Maurice

2
Wenn Sie erneut auf denselben Link klicken, funktioniert dies nicht. Hat jemand diese Funktion ausgeführt, wenn der Benutzer auf denselben Ankerlink geklickt hat <a [routerLink]="['/faq']" fragment="section6">?
Junior Mayhé

@JuniorM Hast du das jemals herausgefunden? Ich habe das gleiche Problem.
Der Muffin-Mann

@ Muffin, versuchen Sie es mit so etwas wie diesem github.com/juniormayhe/Mailing/blob/master/Mailing.SPA/src/app/…
Junior Mayhé

1
Dies erfordert mehr Belichtung. Dies ist eine bessere Antwort IMO. Die meisten Leute werden zu dem Abschnitt springen wollen.
Iamtravisw

44

Tut mir leid, dass ich etwas spät geantwortet habe. In der Angular Routing-Dokumentation gibt es eine vordefinierte Funktion, die uns beim Routing mit einem Hashtag zum Seitenanker hilft, dh anchorScrolling: 'enabled'

Schritt 1: - Importieren Sie zuerst das RouterModule in die Datei app.module.ts: -

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

Schritt 2: - Gehen Sie zur HTML-Seite, erstellen Sie die Navigation und fügen Sie zwei wichtige Attribute wie [routerLink] und Fragment hinzu, um die jeweiligen Div-IDs abzugleichen : -

<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>

Schritt 3: - Erstellen Sie einen Abschnitt / Div, indem Sie den ID-Namen mit dem Fragment abgleichen : -

<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>

Als Referenz habe ich das folgende Beispiel hinzugefügt, indem ich eine kleine Demo erstellt habe, die zur Lösung Ihres Problems beiträgt.

Demo: https://routing-hashtag-page-anchors.stackblitz.io/


Vielen Dank dafür. Sauber, prägnant und es funktioniert!
Belmiris

2
Ja, danke, für das automatische Scrollen beim Laden der Seite mit Angular 7 müssen Sie nur scrollPositionRestoration: 'enabled',unter anchorScrolling-Option hinzufügen :)
Mickaël

Dadurch wird der Hash ordnungsgemäß an das Ende meiner URL angehängt, aber nicht mit dem gleichnamigen Div verankert. Ich bin mir nicht sicher, was ich vermisse. Ich folgte den drei obigen Schritten.
Oaklandrichie

@oaklandrichie: Kannst du hier jsfiddle / stackblitz Code teilen? Ich kann Ihnen helfen
Naheed Shareef

Diese Antwort sollte auf jeden Fall akzeptiert werden, funktioniert wie Charme!
Kiss Koppány

25

Ein bisschen spät, aber hier ist eine Antwort, die funktioniert hat:

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

Und in der Komponente:

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

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

Das Obige scrollt nicht automatisch zur Ansicht, wenn Sie bereits auf einer Seite mit einem Anker landen. Daher habe ich die obige Lösung in meinem ngInit verwendet, damit es auch damit funktioniert:

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); }
        }
      }
    });
  }

Stellen Sie sicher, dass Sie Router, ActivatedRoute und NavigationEnd am Anfang Ihrer Komponente importieren, und alles sollte einsatzbereit sein.

Quelle


4
Funktioniert bei mir! Wenn Sie innerhalb derselben Seite navigieren möchten, auf der Sie sich bereits befinden, verwenden Sie [routerLink] = "['.']"
Raoul

1
Könntest du das weiter erklären? Dieser Teil document.querySelector ( "#" + f )gibt mir einen Fehler, weil er einen Selektor erwartet, keinen String.
Maurice

1
@Maurice für mich funktioniert das: element.scrollIntoView()(ohne elementan die Funktion zu übergeben). Verwenden Sie Folgendes, um es glatt zu machen : element.scrollIntoView({block: "end", behavior: "smooth"}).
Herr B.

Intellisense hier zeigt, dass onAnchorClick()wir innerhalb einen Booleschen Wert an scrollIntoView übergeben müssen : if (element) { element.scrollIntoView(true); }. Jetzt kann ich zweimal auf den gleichen Link klicken und scrollen funktioniert
Junior Mayhé

18

Keine der vorherigen Antworten hat bei mir funktioniert. In einem letzten Versuch habe ich in meiner Vorlage versucht:

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

Mit diesem in meiner .ts:

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

Und es funktioniert wie erwartet für interne Links. Hierbei werden keine Ankertags verwendet, sodass die URL überhaupt nicht berührt wird.


1
einfach und leicht
WasiF

6

Die oben genannten Lösungen haben bei mir nicht funktioniert ... Dieser hat es geschafft:

Bereiten Sie sich zunächst MyAppComponentauf das automatische Scrollen in ngAfterViewChecked () vor ...

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 );

              }
            }
          } );
    }

  }

}

Navigieren Sie dann zum my-app-routeSenden eines prodIDHashtags

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 } );
  }

}

Down Voting ohne Kommentare oder Erklärung ... es ist keine gute Praxis ...
JavierFuentes

Das hat bei mir funktioniert! Warum sollten Sie ngAfterViewChecked anstelle von ngInit verwenden?
Antoine Boisier-Michaud

Vielen Dank an AntoineBoisier-Michaud für Ihr positives Feedback. ngInit wird nicht immer ausgelöst, was ich in meinem Projekt brauche ... ngAfterViewChecked macht es. Können Sie diese Lösung bitte positiv bewerten? Vielen Dank.
JavierFuentes

6

Alle anderen Antworten funktionieren mit Angular Version <6.1. Wenn Sie jedoch die neueste Version haben, müssen Sie diese hässlichen Hacks nicht ausführen, da Angular das Problem behoben hat.

Hier ist der Link zur Ausgabe

Alles, was Sie tun müssen, ist scrollOffsetdie Option des zweiten Argumentes der RouterModule.forRootMethode.

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled',
      anchorScrolling: 'enabled',
      scrollOffset: [0, 64] // [x, y]
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

2
Funktioniert dies für externe Links? Sagen Sie von einer anderen Website, ich klicke auf www.abc.com #
sectionToScrollTo

anchorScrolling funktioniert nicht, wenn Sie * ngIf ausgiebig nutzen, da es zu früh springt :-(
Jojo.Lechelt

Das einzige Problem, das ich damit hatte, ist das Timing - es neigt dazu, zum Anker zu springen, bevor das Styling eines Elements vollständig gerendert ist, was dazu führt, dass die Positionierung deaktiviert ist. Wäre schön, wenn Sie eine Verzögerung hinzufügen könnten :)
Charly

5

Verwenden Sie dies für das Routermodul in app-routing.module.ts:

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

Dies wird in Ihrem HTML sein:

<a href="#/users/123#userInfo">

4

In der HTML-Datei:

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

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

In der ts-Datei:

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();
  }
}

Der querySelector kann leicht in eine Direktive namens scrolllTo eingefügt werden. URL wäre <a scrollTo="test1" [routerLink‹="['./'‹"> Zum Abschnitt Test 1 gehen </a>
John Peters

3

Da die Fragment-Eigenschaft immer noch kein Anker-Scrollen bietet, hat diese Problemumgehung den Trick für mich getan:

<div [routerLink]="['somepath']" fragment="Test">
  <a href="#Test">Jump to 'Test' anchor </a>
</div>

3

Zusätzlich zu Kalyoyans Antwort ist dieses Abonnement an den Router gebunden und bleibt so lange bestehen, bis die Seite vollständig aktualisiert ist. Stellen Sie beim Abonnieren von Router-Ereignissen in einer Komponente sicher, dass Sie sich in ngOnDestroy abmelden:

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();
  }
}

Ich dachte, Abonnements für Routenereignisse wurden automatisch abgerissen.

3

Ich habe das gerade auf meiner eigenen Website zum Laufen gebracht, also dachte ich, es würde sich lohnen, meine Lösung hier zu veröffentlichen.

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

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

Stellen Sie dann in Ihrer Komponente Folgendes sicher:

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

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

Ich denke, dass es besser ist, nur element.scrollIntoView()oder zu schreiben element.scrollIntoView(true). Ihre Version wurde nicht für mich kompiliert (möglicherweise wegen strictNullChecks?).
David L.

3

Nachdem ich alle Lösungen gelesen hatte, suchte ich nach einer Komponente und fand eine, die genau das tut, was die ursprüngliche Frage verlangte: Scrollen zu Ankerlinks. https://www.npmjs.com/package/ng2-scroll-to

Bei der Installation verwenden Sie folgende Syntax:

// 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 {
}

Es hat wirklich gut für mich funktioniert.


Benutze das Rad, erfinde es nicht noch einmal;)
Yogen Rai

Haben Sie sich den Code hinter dieser Komponente angesehen? Es sieht sehr fragil aus - das Projekt hat auch 14 offene Probleme - darunter Dinge wie nicht vorhandenes Element, Ziele null, nicht zum Element scrollen, Probleme mit der Browserunterstützung.
Drenai

funktioniert nicht, wenn Sie ein Kind (Kind hat verankerte Entitäten und / oder Ankernamen) in der übergeordneten Komponente haben, es aktualisiert nur die Seite
Sasha Bond

3

Eine einfache Lösung, die für Seiten ohne Abfrageparameter funktioniert, ist Browser-Vorwärts- / Rückwärts-, Router- und Deep-Linking-kompatibel.

<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();
    }
}

Das Zeitlimit besteht einfach darin, dass die Seite alle dynamischen Daten laden kann, die durch eine * ngIf "geschützt" sind. Dies kann auch verwendet werden, um beim Ändern der Route zum Anfang der Seite zu scrollen. Geben Sie einfach ein Standard-Tag für den oberen Anker an.


1

Hier ist eine weitere Problemumgehung unter Bezugnahme auf die Antwort von JavierFuentes:

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

im Skript:

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);
        }
}

Auf diese Weise kann der Benutzer direkt zum Element scrollen, wenn der Benutzer direkt auf der Seite mit dem Hashtag in der URL landet.

Aber in diesem Fall habe ich Route Fragment in abonniert, wird ngAfterViewCheckedaber ngAfterViewChecked()kontinuierlich aufgerufen ngDoCheckund es erlaubt dem Benutzer nicht, nach oben zu scrollen. routeFragmentSubscription.unsubscribeDies wird nach einer Zeitüberschreitung von 0 Millis aufgerufen, nachdem die Ansicht zum Element gescrollt wurde.

Zusätzlich wird eine gotoHashtagMethode definiert, um zum Element zu scrollen, wenn der Benutzer speziell auf das Ankertag klickt.

Aktualisieren:

Wenn die URL Querystrings enthält, werden die Querystrings [routerLink]="['self-route', id]"im Anker nicht beibehalten. Ich habe versucht, die gleiche Problemumgehung zu finden:

<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);
}

1

Dieser arbeitet für mich !! Damit das Tag dynamisch verankert wird, müssen Sie warten, bis es gerendert ist

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>

Meine ts-Datei:

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();
    }
}

Vergessen Sie nicht , dass zu importieren ViewChildren, QueryListetc .. und einige Konstruktor hinzufügen ActivatedRoute!!


1

Im Gegensatz zu anderen Antworten würde ich zusätzlich auch hinzufügen , focus()zusammen mit scrollIntoView(). Außerdem verwende ich, setTimeoutda es sonst beim Ändern der URL nach oben springt. Ich bin mir nicht sicher, was der Grund dafür war, aber es scheintsetTimeout dies die Problemumgehung bewirkt.

Ursprung:

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

Ziel:

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

Typoskript:

scrollIntoView(anchorHash) {
    setTimeout(() => {
        const anchor = document.getElementById(anchorHash);
        if (anchor) {
            anchor.focus();
            anchor.scrollIntoView();
        }
    });
}

1

Ich hatte das gleiche Problem. Die Lösung: Verwenden des View Port Scroller https://angular.io/api/common/ViewportScroller#scrolltoanchor

- app-routing.module.ts Code:

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

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

- Komponenten-HTML

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

- Komponentencode:

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


    export class ParametrageComponent {

      constructor(private viewScroller: ViewportScroller) {}

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

    }

1

Wenn es nicht wichtig ist, diese Element-IDs an die URL anzuhängen, sollten Sie sich diesen Link ansehen:

Winkel 2 - Ankerverknüpfungen zum Element auf der aktuellen Seite

// 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
  }
 }


0

Ich habe gerade ein sehr nützliches Plugin getestet, das in nmp verfügbar ist - ngx-scroll-to , was für mich großartig funktioniert. Es ist jedoch für Angular 4+ konzipiert, aber vielleicht findet jemand diese Antwort hilfreich.


0

Ich habe die meisten dieser Lösungen ausprobiert, aber es gab Probleme beim Verlassen und Zurückkommen mit einem anderen Fragment, das nicht funktionieren würde. Deshalb habe ich etwas anderes gemacht, das zu 100% funktioniert, und den hässlichen Hash in der URL beseitigt.

Hier ist ein besserer Weg als das, was ich bisher gesehen habe.

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();
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.