Wróć do strony głównej

ANGULAR 2 Resolver

RESOLVER – dostarczamy dane przed aktywacją routa

W tym artykule przyjrzymy się bliżej funkcji Resolver, która może nam zwrócić Promise<any>, Observable<any> lub po prostu jakieś dane. Zapewne sporo z Was dokładnie wie czemu służy Resolve, kojarząc go z Ui-Routera w Angularze 1.x. Dla niewtajemniczonych, Route resolvers służy dostarczeniu danych do Routa. Przed aktywacją Routa, a jeszcze prościej mówiąc, zmuszamy naszą aplikację, aby pokazał widok dopiero jak dane zostaną dostarczone.

Dla łatwiejszej analizy dalszej treści, w linku live example przykładu, który rozpatrzymy:

LIVE EXAMPLE

W aplikacji powyżej, mamy listę userów, klikając na username danego usera, przechodzimy do komponentu z jego szczegółami, a kontroler ów komponentu woła asynchronicznie o dane usera.

Z racji, że call do backendu jest asynchroniczny, to podczas inicjalizacji komponentu, przekazany obiekt „user” do widoku przyjmuje wartość undefined ponieważ dane usera nie zostały jeszcze pobrane, co prowadzi do tego, że widok nie zostanie poprawnie sparsowany.

Zapewne wielu z Was może to dziwić, gdyż Angular 1.x nie miał problemu z parsowaniem wartości null & undefined w interpolacjach, natomiast Angular 2 domyślnie już na to nie pozwala. W naszym przypadku, próba użycia na widoku (user-detail.component.html):

konsola zwróci nam błąd:

Oczywiście możemy się przed tym zabezpieczyć używająć elvisów na widoku:

Na dłuższą metę, używanie wszędzie „elvisów” może być męczące, zwłaszcza, że nie wszędzie możemy ich użyć (np w ngModel lub w dyrektywach routerLink).

IMPLEMENTACJA RESOLVERA

Aby skorzystać z funkcjonalności Resolve, napiszemy serwis, który implementuje interfejs Resolve, udostępniający nam metodę resolve(). Metoda resolve() może przyjąć dwa parametry, route: ActivatedRouteSnapshot oraz state: RouterStateSnapshot.

Dzięki naszemu serwisowi, będziemy mogli przygotować dane usera przed aktywacją Routa danego komponentu. Powstałą klasę UserResolve, zawołamy w konfiguracji naszego routingu oraz dodamy do providers głównego modułu aplikacji.

Czym jest route.params[’id’]  przekazane jako parametr do metody getUser? Jeśli zajrzymy do dokumentacji ActivatedRouteSnapshot, widzimy, że posiada pole „params”. Params odczytuje wartość id, która pojawia się w URLu, w naszym przypadku jest to ID danego usera. Oczywiście params[’id’] jest dlatego, że nasz path w konfiguracji routingu jest określony jako:

Jeśli nazwiesz swojego patha do danego komponentu przykładowo 'products/:name’,  otrzymasz do niego dostęp poprzez params[’name’].

Dodajemy nasz serwis do providers w głównym module (module.app.ts):

Przekazujemy resolver w routingu (app-routing.module.ts):

Oraz przypisujemy wartość do usera w user-detail.component:

Interfejs ActivatedRoute daje nam dostęp do snapshota o typie ActivatedRouteSnapshot (reprezentacja aktywnego stanu routa w danym momencie), z kolei ActivatedRouteSnapshot posiada dostęp do obiektu data, który reprezentuje statyczne dane lub otrzymane poprzez Resolve. Z racji, że w konfiguracji routingu, nasz Resolver został przypisany do property 'user’, otrzymujemy dostęp do naszego obiektu poprzez

Voila! Link do live example po dodaniu resolvera:

LIVE EXAMPLE

Zamiast użycia snapshota, możesz również podłączyć się pod strumień z danymi, poprzez  subscribe, tzn.:

PODSUMOWANIE

Resolver nie musi być klasą, można również do Resolve w konfiguracji routingu przypisać funkcję pobraną z useValue z providers. W przypadku zainteresowania takim przypadkiem, polecam sprawdzić drugi przykład z API Angulara:

https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html

O autorze

Tomasz Nastały

JavaScript Developer, entuzjasta frameworka Angular oraz TypeScripta. Na co dzień lubię dzielić się wiedzą poprzez prowadzenie zajęć w jednym z trójmiejskich bootcampów i nagrywaniem kursów z Angulara.

Zapisz się do naszego newslettera. Bądź na bieżąco z najnowszymi trendami, poradami, meetupami i stań się częścią społeczności Angulara w Polsce. Rynek pracy docenia członków społeczności.

6 komentarzy

  1. Pingback: ANGULAR – ROUTER EVENTS I SPINNER

  2. Pingback: Rozmowa o pracę na Angular Developera - jakich pytań możesz się spodziewać? - No Fluff Jobs - blog

  3. magos

    Tomek, dzięki za wyjaśnienie. Ja tylko dodam, że w przypadku, kiedy nasz Resolve zwraca Observable musimy zasubskrybować się do obiektu data ActivatedRoute, a nie snapshota. Drobna pomyłka w ostatnim listeningu:

    this.route.data.subscribe((data) => this.user = data['user'])

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *