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’ w 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!