Routing Angular2 z hasłem do kotwicy strony


120

Chciałbym dodać kilka linków na mojej stronie Angular2, które po kliknięciu będą przeskakiwać do określonych pozycji na tej stronie, tak jak robią to zwykłe hashtagi. Więc linki wyglądałyby tak

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

itp.

Wydaje mi się, że nie potrzebuję HashLocationStrategy, ponieważ nie przeszkadza mi normalny sposób Angular2, ale jeśli dodam bezpośrednio, link faktycznie przeskoczy do katalogu głównego, a nie gdzieś na tej samej stronie. Każdy kierunek jest doceniany, dzięki.

Odpowiedzi:


130

Aktualizacja

Jest to teraz obsługiwane

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

Dodaj poniższy kod do swojego komponentu, aby go przewijać

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

Oryginalny

Jest to znany problem, który można śledzić pod adresem https://github.com/angular/angular/issues/6595


1
@invot zmienna z ciągiem znaków (na przykład to, co 123jest w pytaniu) przy założeniu, że ścieżka trasy oczekuje parametru takiego jak{ path: 'users/:id', ....}
Günter Zöchbauer

2
Jeśli chcesz przewinąć do kotwicy, zobacz ten post: github.com/angular/angular/issues/6595
Pere Pages

12
Uwaga: to nadal się nie przewija
Martín Coll,

2
tak, działa z setTimeout, jeśli znajdę lepsze rozwiązanie, dam ci znać
Amr Ibrahim

1
Dla tych, którzy mają trudności z przewijaniem do identyfikatorów podobnych do liczb, pamiętaj, że 01lub 100nie są one prawidłowymi selektorami CSS. Możesz dodać literę lub coś, co sprawi, że będzie to prawidłowy selektor. Tak więc nadal przechodziłbyś 01jako fragment, ale idmusiałoby to być coś podobnego, d01a zatem document.querySelector('#d'+id)pasowałoby.
pop

52

Chociaż odpowiedź Güntera jest poprawna, nie obejmuje ona części dotyczącej „skoku do” znacznika kotwicy .

Dlatego dodatkowo do:

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

... w komponencie (nadrzędnym), w którym potrzebujesz zachowania „przejdź do”, dodaj:

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

  }
}

Należy pamiętać, że jest to obejście ! Śledź ten problem na githubie, aby uzyskać przyszłe aktualizacje. Podziękowania dla Victora Savkina za dostarczenie rozwiązania!


witam, tworzę stronę z często zadawanymi pytaniami, na której możesz przejść do odpowiedzi, klikając pytanie zdefiniowane na liście u góry strony. Czyli użytkownik jest już na bieżącej stronie, kiedy przeskakuje do zakotwiczenia. Jeśli chcę, aby atrybut routerLink działał, muszę podać "['../faq']"jako wartość, w przeciwnym razie spróbuje przejść do / faq / faq / # anchor, insteaf of / faq / # anchor. Czy to jest właściwy sposób, czy też istnieje bardziej elegancki sposób odnoszenia się do bieżącej strony w routerze? Ponadto document.querySelector("#" + tree.fragment);daje mi nieprawidłowy błąd selektora. Czy jesteś pewien, że to prawda? Dziękuję
Maurice

2
po ponownym kliknięciu tego samego łącza nie działa. Czy ktoś sprawił, że to zadziałało, gdyby użytkownik kliknął ten sam link kotwicy <a [routerLink]="['/faq']" fragment="section6">?
Junior Mayhé

@JuniorM Czy kiedykolwiek to rozgryzłeś? Mam ten sam problem.
The Muffin Man


1
To wymaga większej ekspozycji. To lepsza odpowiedź IMO. Większość ludzi będzie chciała przejść do tej sekcji.
iamtravisw

44

Przepraszam, że odpowiedziałem trochę późno; W dokumentacji Angular Routing znajduje się predefiniowana funkcja, która pomaga nam w routingu z hashtagiem do kotwicy strony, tj. AnchorScrolling: 'enabled'

Krok 1: - Najpierw zaimportuj RouterModule do pliku app.module.ts: -

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

Krok 2: - Przejdź do strony HTML, utwórz nawigację i dodaj dwa ważne atrybuty, takie jak [routerLink] i fragment w celu dopasowania odpowiednich identyfikatorów Div : -

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

Step-3: - Utwórz sekcję / div, dopasowując nazwę ID do fragmentu : -

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

W celach informacyjnych dodałem poniższy przykład, tworząc małe demo, które pomaga rozwiązać problem.

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


Bardzo dziękuję za to. Czysto, zwięźle i działa!
Belmiris

2
Tak, dzięki, za automatyczne przewijanie po załadowaniu strony w Angular 7, wystarczy dodać scrollPositionRestoration: 'enabled',opcję pod zakotwiczeniem Przewijanie :)
Mickaël

Spowoduje to prawidłowe dołączenie skrótu na końcu mojego adresu URL, ale nie zakotwicza go do elementu div o tej samej nazwie. Nie jestem pewien, czego mi brakuje. Wykonałem trzy powyższe kroki.
oaklandrichie

@oaklandrichie: Czy możesz tutaj udostępnić kod jsfiddle / stackblitz. Mogę ci pomóc
Naheed Shareef

ta odpowiedź zdecydowanie powinna zostać zaakceptowana, działa jak urok!
Pocałuj Koppány

25

Trochę późno, ale oto odpowiedź, którą znalazłem, która działa:

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

A w komponencie:

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

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

Powyższe nie przewija się automatycznie do widoku, jeśli wylądujesz na stronie z kotwicą, więc użyłem powyższego rozwiązania w moim ngInit, aby to również działało:

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

Pamiętaj, aby zaimportować Router, ActivatedRoute i NavigationEnd na początku komponentu i wszystko powinno być gotowe.

Źródło


4
Pracuje dla mnie! Jeśli chcesz nawigować po tej samej stronie, na której już jesteś, użyj [routerLink] = "['.']"
Raoul,

1
czy mógłbyś wyjaśnić dalej? ta część document.querySelector ( "#" + f )daje mi błąd, ponieważ oczekuje selektora, a nie łańcucha.
Maurice

1
@Maurice dla mnie to działa: element.scrollIntoView()(bez przechodzenia elementdo funkcji). Aby ją gładką, użyj tego: element.scrollIntoView({block: "end", behavior: "smooth"}).
Mr. B.

IntelliSense tutaj pokazuje, że w ciągu onAnchorClick()musimy zdać logiczną do scrollIntoView: if (element) { element.scrollIntoView(true); }. Teraz mogę dwukrotnie kliknąć ten sam link i przewijać prace
Junior Mayhé

18

Żadna z poprzednich odpowiedzi nie działała dla mnie. W ostatnim wysiłku spróbowałem w moim szablonie:

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

Z tym w moim .ts:

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

I działa zgodnie z oczekiwaniami w przypadku linków wewnętrznych. To faktycznie nie używa tagów kotwicy, więc w ogóle nie dotyka adresu URL.


1
proste i łatwe
WasiF

6

Powyższe rozwiązania nie działały dla mnie ... Ten zrobił to:

Najpierw przygotuj się MyAppComponentdo automatycznego przewijania w 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 );

              }
            }
          } );
    }

  }

}

Następnie przejdź do my-app-routewysyłania prodIDhashtagu

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

}

Głosowanie
przeciw

To zadziałało dla mnie! Dlaczego jednak używać ngAfterViewChecked zamiast ngInit?
Antoine Boisier-Michaud

Dziękuję @ AntoineBoisier-Michaud za pozytywne opinie. ngInit nie uruchamia się zawsze, czego potrzebuję w moim projekcie ... ngAfterViewChecked to robi. Czy możesz zagłosować za tym rozwiązaniem? Dzięki.
JavierFuentes

6

Wszystkie inne odpowiedzi będą działać w Angular w wersji <6.1. Ale jeśli masz najnowszą wersję, nie będziesz musiał robić tych brzydkich hacków, ponieważ Angular rozwiązał problem.

tutaj jest link do wydania

Wszystko, co musisz zrobić, to ustawić scrollOffsetopcję drugiego argumentu RouterModule.forRootmetody.

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

2
czy to zadziała w przypadku linków zewnętrznych? powiedzmy, że z innej strony internetowej klikam www.abc.com #
sectionToScrollTo

anchorScrolling nie działa, jeśli intensywnie korzystasz z * ngIf, ponieważ przeskakuje do wczesnego :-(
Jojo.Lechelt

Jedynym problemem, jaki miałem z tym, jest synchronizacja - ma tendencję do przeskakiwania do kotwicy, zanim stylizacja jakiegoś elementu zostanie w pełni wyrenderowana, powodując wyłączenie pozycjonowania. Byłoby miło, gdybyś mógł dodać opóźnienie :)
Charly

5

Użyj tego dla modułu routera w app-routing.module.ts:

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

To będzie w Twoim HTML:

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

4

W pliku html:

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

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

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

QuerySelector można łatwo umieścić w dyrektywie o nazwie scrolllTo. Adres URL to <a scrollTo="test1" [routerLink]="['./']"> Przejdź do sekcji Test 1 </a>
John Peters

3

Ponieważ właściwość fragment nadal nie zapewnia przewijania kotwicy, to obejście załatwiło sprawę:

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

3

Dodając do odpowiedzi Kalyoyan , ta subskrypcja jest powiązana z routerem i będzie obowiązywać do pełnego odświeżenia strony. Podczas subskrybowania zdarzeń routera w komponencie należy zrezygnować z subskrypcji w 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();
  }
}

Wydawało mi się, że subskrypcje na trasy koncertowe zostały automatycznie zniesione.

3

Właśnie to działa na mojej własnej stronie internetowej, więc pomyślałem, że warto opublikować tutaj moje rozwiązanie.

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

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

A następnie w swoim komponencie upewnij się, że uwzględnisz to:

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

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

Myślę, że lepiej pisać po prostu element.scrollIntoView()lub element.scrollIntoView(true). Twoja wersja nie skompilowała się dla mnie (może z powodu surowych NullChecks?).
David L.,

3

Po przeczytaniu wszystkich rozwiązań szukałem komponentu i znalazłem taki, który robi dokładnie to, o co chodziło w pierwotnym pytaniu: przewijanie do linków zakotwiczenia. https://www.npmjs.com/package/ng2-scroll-to

Podczas instalacji używasz składni takiej jak:

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

U mnie zadziałało naprawdę dobrze.


Użyj koła, nie wymyślaj go ponownie;)
Yogen Rai

Czy spojrzałeś na kod za tym komponentem? Wygląda bardzo krucho - projekt ma również 14 otwartych problemów - które obejmują takie rzeczy, jak nieistniejący element, cel null, brak przewijania do elementu, problemy z obsługą przeglądarki.
Drenai

nie działa, gdy masz dziecko (dziecko ma zakotwiczone elementy i / lub nazwy kotwic) w komponencie nadrzędnym, po prostu odświeża stronę
Sasha Bond

3

Proste rozwiązanie, które działa w przypadku stron bez parametrów zapytania, jest zgodne z przeglądarką wstecz / dalej, routerami i głębokimi linkami.

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

Limit czasu to po prostu zezwolenie stronie na załadowanie dowolnych danych dynamicznych „chronionych” przez * ngIf. Można go również użyć do przewinięcia na górę strony podczas zmiany trasy - wystarczy podać domyślny znacznik górnej kotwicy.


2

jeśli nie ma znaczenia, aby te identyfikatory elementów były dołączane do adresu URL, powinieneś rozważyć ten link:

Kątowy 2 - Zakotwicz łącza do elementu na bieżącej stronie

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


1

Oto kolejne obejście z odniesieniem do odpowiedzi JavierFuentes:

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

w skrypcie:

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

Pozwala to użytkownikowi na bezpośrednie przewinięcie do elementu, jeśli użytkownik trafi bezpośrednio na stronę mającą hashtag w adresie URL.

Ale w tym przypadku subskrybowałem fragment trasy, ngAfterViewCheckedale ngAfterViewChecked()jest wywoływany w sposób ciągły za każdym razem ngDoChecki nie pozwala użytkownikowi przewijać z powrotem do góry, więcrouteFragmentSubscription.unsubscribe jest wywoływany po przekroczeniu limitu czasu 0 milisek po przewinięciu widoku do elementu.

Dodatkowo gotoHashtagzdefiniowano metodę przewijania do elementu, gdy użytkownik kliknie znacznik kotwicy.

Aktualizacja:

Jeśli adres URL ma querystringi, [routerLink]="['self-route', id]"w zakotwiczeniu nie zachowa tych zapytań. Próbowałem zastosować obejście tego samego problemu:

<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

Ten działa dla mnie !! Ten ngFor tak dynamicznie zakotwicza tag, musisz poczekać, aż wyrenderują

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>

Mój plik 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();
    }
}

Nie zapomnij, że import ViewChildren, QueryListetc .. i dodać konstruktora ActivatedRoute!!


1

W przeciwieństwie do innych odpowiedzi, dodałbym dodatkowo focus()wraz z scrollIntoView(). Używam również, setTimeoutponieważ przeskakuje na górę w przeciwnym razie podczas zmiany adresu URL. Nie jestem pewien, jaki był tego powód, ale wydaje się setTimeout, że obejście.

Pochodzenie:

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

Miejsce docelowe:

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

Maszynopis:

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

1

Miałem ten sam problem. Rozwiązanie: użycie View port Scroller https://angular.io/api/common/ViewportScroller#scrolltoanchor

- kod app-routing.module.ts:

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

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

- Komponent HTML

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

- Kod komponentu:

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


    export class ParametrageComponent {

      constructor(private viewScroller: ViewportScroller) {}

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

    }

0

Właśnie przetestowałem bardzo przydatną wtyczkę dostępną w nmp - ngx-scroll-to , która działa świetnie. Jest jednak przeznaczony dla Angular 4+, ale może ktoś uzna tę odpowiedź za pomocną.


0

Wypróbowałem większość tych rozwiązań, ale napotkałem problemy z opuszczeniem i powrotem z innym fragmentem, który nie zadziałał, więc zrobiłem coś innego, co działa w 100% i pozbyłem się brzydkiego hasha w adresie URL.

tl; dr tutaj jest lepszy sposób niż to, co widziałem do tej pory.

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();
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.