Angular2-routering met hashtag naar pagina-anker

Ik wil enkele links op mijn Angular2-pagina toevoegen, die wanneer erop wordt geklikt, naar specifieke posities binnenop die pagina springen, zoals wat normale hashtags doen. Dus de links zouden zoiets zijn als

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

enz.

Ik denk niet dat ik HashLocationStrategy nodig heb, aangezien ik de normale Angular2-manier prima vind, maar als ik direct toevoeg, zou de link naar de root springen, niet ergens op dezelfde pagina. Elke richting wordt gewaardeerd, bedankt.


Antwoord 1, autoriteit 100%

Bijwerken

Dit wordt nu ondersteund

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

Voeg onderstaande code toe aan uw component om te scrollen

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

Origineel

Dit is een bekend probleem en wordt bijgehouden op https://github.com/angular/angular/ problemen/6595


Antwoord 2, autoriteit 43%

Sorry dat ik wat laat reageer; Er is een vooraf gedefinieerde functie in de Angular Routing Documentation die ons helpt bij het routeren met een hashtag naar pagina-anker, d.w.z. anchorScrolling: ‘enabled’

Stap-1:-Importeer eerst de RouterModulein het app.module.ts-bestand:-

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

Stap-2:-Ga naar de HTML-pagina, maak de navigatie en voeg twee belangrijke attributen toe, zoals [routerLink]en fragmentvoor overeenkomend met de respectievelijke Div ID’s:-

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

Stap-3:-Maak een sectie/div door de ID-naamte matchen met het 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>

Ter referentie heb ik het onderstaande voorbeeld toegevoegd door een kleine demo te maken waarmee u uw probleem kunt oplossen.

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


Antwoord 3, autoriteit 34%

Hoewel Günter’s antwoordcorrect is, het dekt niet het gedeelte “springen naar” het ankertaggedeelte .

Daarom, als aanvulling op:

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

… in de component (ouder) waar je een “spring naar”-gedrag nodig hebt, voeg je toe:

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

Houd er rekening mee dat dit een tijdelijke oplossing is! Volg dit github-probleemvoor toekomstige updates. Met dank aan Victor Savkinvoor het leveren van de oplossing!


Antwoord 4, autoriteit 16%

Een beetje laat, maar hier is een antwoord dat ik heb gevonden dat werkt:

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

En in de component:

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

Het bovenstaande scrolt niet automatisch naar de weergave als je al op een pagina met een anker terechtkomt, dus ik heb de bovenstaande oplossing in mijn ngInit gebruikt, zodat het daar ook mee zou kunnen werken:

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

Zorg ervoor dat u Router, ActivatedRoute en NavigationEnd aan het begin van uw component importeert en het zou allemaal goed moeten zijn om te gaan.

Bron


Antwoord 5, autoriteit 12%

Geen van de vorige antwoorden werkte voor mij. In een laatste wanhopige poging probeerde ik in mijn sjabloon:

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

Met dit in mijn .ts:

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

En het werkt zoals verwacht voor interne links. Dit gebruikt eigenlijk geen ankertags, dus het zou de URL helemaal niet raken.


Antwoord 6, autoriteit 5%

Als het niet uitmaakt dat deze element-ID’s aan de url worden toegevoegd, kunt u overwegen deze link te bekijken:

Angular 2 – ankerlinks naar element op huidige pagina

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

Snippet uitvouwen


Antwoord 7, autoriteit 4%

Bovenstaande oplossingen werkten niet voor mij… Deze deed het:

Bereid eerst MyAppComponentvoor op automatisch scrollen in 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 );
              }
            }
          } );
    }
  }
}

Navigeer vervolgens naar my-app-routeen verzend 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 } );
  }
}

Antwoord 8, autoriteit 4%

Alle andere antwoorden werken op de Angular-versie < 6.1. Maar als je de nieuwste versie hebt, hoef je deze lelijke hacks niet uit te voeren, omdat Angular het probleem heeft opgelost.

hier is de link om uit te geven

Het enige wat u hoeft te doen is scrollOffsetin te stellen met de optie van het tweede argument van de methodeRouterModule.forRoot.

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

Antwoord 9, autoriteit 4%

In html-bestand:

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

In ts-bestand:

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

Antwoord 10, autoriteit 3%

Gebruik dit voor de routermodule in app-routing.module.ts:

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

Dit staat in je HTML:

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

Antwoord 11, autoriteit 2%

Als aanvulling op het antwoordvan Kalyoyan, is dit abonnement gekoppeld aan de router en blijft het bestaan ​​totdat de pagina volledig is vernieuwd. Wanneer u zich abonneert op routergebeurtenissen in een component, zorg er dan voor dat u zich afmeldt in 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();
  }
}

Antwoord 12, autoriteit 2%

Aangezien de fragment-eigenschap nog steeds niet voorziet in scrollen met ankers, heeft deze tijdelijke oplossing mij geholpen:

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

Antwoord 13, autoriteit 2%

Ik heb dit zojuist op mijn eigen website laten werken, dus ik dacht dat het de moeite waard zou zijn om mijn oplossing hier te posten.

<a [routerLink]="baseUrlGoesHere" fragment="nameOfYourAnchorGoesHere">Link Text!</a>
<a name="nameOfYourAnchorGoesHere"></a>
<div>They're trying to anchor to me!</div>

En zorg ervoor dat u dit in uw component opneemt:

import { ActivatedRoute } from '@angular/router';
 constructor(private route: ActivatedRoute) { 
     this.route.fragment.subscribe ( f => {
         const element = document.querySelector ( "#" + f )
         if ( element ) element.scrollIntoView ( element )
     });
 }

Antwoord 14, autoriteit 2%

Na het lezen van alle oplossingen, zocht ik naar een component en ik vond er een die precies doet waar de oorspronkelijke vraag om vroeg: scrollen naar ankerlinks. https://www.npmjs.com/package/ng2-scroll-to

Als je het installeert, gebruik je een syntaxis zoals:

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

Het heeft heel goed gewerkt voor mij.


Antwoord 15, autoriteit 2%

Een eenvoudige oplossing die werkt voor pagina’s zonder queryparameters, is browser back/forward, router en deep-linking-compatibel.

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

De time-out is eenvoudigweg om de pagina toe te staan ​​alle dynamische gegevens “beschermd” te laden door een * NGIF. Dit kan ook worden gebruikt om naar de bovenkant van de pagina te bladeren bij het wijzigen van route – geef gewoon een standaard Top Anchor-tag op.


16

Ik heb zojuist zeer nuttige plug-in getest in NMP – NGX-scroll-to , die goed voor mij werkt. Het is echter ontworpen voor hoekige 4+, maar misschien zal iemand dit antwoord nuttig vinden.

Other episodes