19 lip 2018
5 min

Angular 6.1.0 – Scroll behavior & ViewportScroller

Dzisiaj krótki art o świetnej funkcjonalności, która pojawiła się w nowej wersji Angulara 6.1.0-beta.1. Wielokrotnie irytowało mnie zachowanie scrolla w aplikacjach angularowych i w pewnych przypadkach niestety nie dało się obejść bez serwisu zarządzającego scrollem. Panowie z Angulara wpadli w końcu na genialny pomysł, aby scroll zachowywał się jak na scrolla przystało 😉

Problem scrolla

Wyobraź sobie sytuację, że chcesz przejść do widoku i od razu ustawić wysokość strony na odpowiedniej kotwicy. Przykład:

Template widoku A:

<a routerLink="some-view" fragment="someAnchor" style="margin-top: 300px;display: block">Go to view B</a>

Template widoku B:

<div id="someAnchor" style="margin-top: 600px">B view</div>

Na linku użyłem właściwość fragment, która doklei kotwicę do URLa po przejściu do widoku B:

http://localhost:4200/b-view#someAnchor

Z racji, że div w widoku B ma margines górny ustawiony na 600px, to spodziewam się, że po przejściu na widok B, wartość scroll.Y ustawi się na 600px. Oczekuję również, że jak kliknę w przeglądarce strzałkę wstecz, to scroll wróci na pozycję Y o wartości 300px, no bo przeszedłem z widoku właśnie na takiej wysokości. Niestety tak się nie dzieje 🙁 Standardowo przeglądarka obsługuje takie zachowanie, ale w przypadku aplikacji SPA nie jest to już domyślna funkcjonalność.

AnchorScrolling & ScrollPositionRestoration to the rescue!

Od wresji 6.1.0 z pomocą przychodzą nam dwie nowe opcje dla konfiguracji Routera:

@NgModule({
  declarations: [
    AppComponent,
    SomeViewComponent
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot([{ path: 'some-view', component: SomeViewComponent}],
      { anchorScrolling: 'enabled', scrollPositionRestoration: 'enabled'})
  ],
  providers: [],
  bootstrap: [AppComponent]
})

Konfigurację Routera możemy zmienić przekazując obiekt konfiguracyjny jako drugi parametr w metodzie forRoot.

Spójrzmy co mamy nowego do dyspozycjI:

  • anchorScrolling: 'disabled’ | 'enabled’  (domyślnie disabled)
  • scrollPositionRestoration: 'disabled’ | 'top’ | 'enabled’ (domyślnie disabled)

W obu właściwościach disabled jest domyślny, ale to się zmieni w przyszłości na enabled. Wartość ’top’ oznacza, aby po powrocie scrollować zawsze do [0, 0] czyli do góry strony.

ScrollPositionRestoration:  'enabled’ odpowiada za to, aby po powrocie do poprzedniej strony, scroll był na takiej pozycji, z której przyszliśmy.

Natomiast zmiana na ’enabled’anchorScrolling zapewni nam, że po przejściu do URL z kotwicą, przeglądarka przeskoczy scrollem do odpowiedniej wysokości.

Sprawdziłem obie konfiguracje i działają naprawdę świetnie, już nie mogę się doczekać migracji do 6.1.0 :))

ViewportScroller

ViewportScroller to z kolei nowy serwis, który pozwoli nam korzystać z wartości scrolla. Na githubie pojawił się przykład:

import { ViewportScroller } from '@angular/common';
class ListComponent {
    list: any[];
    constructor(router: Router, viewportScroller: ViewportScroller, fetcher: ListFetcher) {
      const scrollEvents = router.events.filter(e => e instanceof Scroll);
      listFetcher.fetch().pipe(withLatestFrom(scrollEvents)).subscribe(([list, e]) => {
          this.list = list;
          if (e.position) {
              viewportScroller.scrollToPosition(e.position);
            } else {
              viewportScroller.scrollToPosition([0, 0]);
            }
        });
    }
}

COMMIT LINK Z PRZYKŁADAMI:  https://github.com/angular/angular/commit/49c5234

Także możemy teraz korzystać ze scrolla dla specyficznego komponentu oraz do ekipy RouterEvents dołączył nowy gracz: Scroll.

Scroll jest ostatnim eventem, wywołanym po NavigationEnd. Zachęcam do przejrzenia linka z commitem i zapoznania się z przykładami i kodem źródłowym. ViewportScroller po prostu opakowuje window.scrollTo w wygodne API. Natomiast nowy Scroll Event tak wygląda:

 * Represents a scrolling event.
 */
export declare class Scroll {
    readonly routerEvent: NavigationEnd;
    readonly position: [number, number] | null;
    readonly anchor: string | null;
    constructor(
    routerEvent: NavigationEnd, 
    position: [number, number] | null, 
    anchor: string | null);
    toString(): string;
}

Jak widzisz, daje nam dostęp do takich właściwości jak pozycja scrolla i kotwicy.

Jeśli nie są znane Ci RouterEvents, to zachęcam do przeczytania artykułu:
http://wp.angular.love/2017/06/17/angular-router-events-i-spinner/

Wkrótce Angular 6.1.0 wejdzie na rynek, na razie jest na etapie RC.0, ale warto pamiętać o tym nowym bajerze z ustawieniem scrolla!

Podziel się artykułem

Zapisz się na nasz newsletter

Dołącz do community Angular.love i bądź na bieżąco z trendami.