Wróć do strony głównej
Angular

Angular InjectionToken

Tworzysz własny komponent? chciałbyś umożliwić użytkownikom definiować globalne ustawienia, które zostaną zaaplikowane na każdej instancji komponentu?

Jeśli tak, to ten wpis jest dla Ciebie 😉 Poczuj moc InjectionTokens!

InjectionToken

Rozważmy następujący przykład:

  • tworzymy komponent, np. FileUploadera (o selektorze <file-uploader></file-uploader>), którego chcemy udostępnić społeczności
  • konfiguracja uploadera jest oparta o domyślny obiekt konfiguracyjny
  • umożliwiamy użytkownikowi zmodyfikować domyślną konfigurację, poprzez przekazanie własnej konfiguracji poprzez dekorator @Input() – <file-uploader [config]=”config”></file-uploader>.

Niby wygodnie…ale jeśli użytkownik ma w aplikacji 100 instancji uploadera, to musi 100 razy przekazać inputa z konfiguracją. Co prawda ciężko mi sobie wyobrazić apkę, gdzie mamy 100 file uploaderów, ale np. kilkaset mat-inputów z Angular Material… jak najbardziej!

Czyż nie byłoby pięknie, jakby użytkownik mógł raz, globalnie skonfigurować swój komponent i nie bawić się w żadne @Input ? No pewnie!

Z pomocą przychodzi klasa InjectionToken:
https://angular.io/api/core/InjectionToken

Dzięki InjectionToken, możemy np. do komponentu dostarczyć obiekt konfiguracyjny, który zostanie zdefiniowany wyłącznie raz, np. w AppModule.

Angular ma bardzo przemyślaną implementację Dependency Injection, z której korzystamy na co dzień tworząc aplikacje angularowe, chociażby w momencie wstrzykiwania zależności do konstruktora klasy komponentu. Dzięki tokenom (tokenem może być np. klasa lub string), Angular potrafi rozróżniać zależności.

FileUploaderComponent

Załóżmy zatem, że tworzymy taki FileUploaderComponent i chcemy umożliwić użytkownikowi dostarczyć globalny obiekt konfiguracyjny.

Rozpoczynamy od stworzenia własnego tokena, który jest instancją klasy InjectionToken i jest eksportowany pod zmienną o ustalonej przez nas nazwie (tu: FILE_UPLOADER_GLOBAL_CONFIG):

Tworzymy również interfejs, który opisze nam możliwą konfigurację.

Teraz pozostaje nam dostarczyć nasz token jako zależność w komponencie. Do dekoratora @Injectmusimy przekazać nazwę naszego tokena (i oczywiście go zaimportować):

I korzystając np. z Object.assign(), łączymy domyślną konfigurację z tą przekazaną globalnie od użytkownika.

Warto również skorzystać z dekoratora @Optional. W przypadku, gdy w konstruktorze oczekujemy dostarczenia danej zależności a nie zostanie ona odnaleziona, to otrzymamy errora (i słusznie). Dzięki @Optional, wskazujemy, że dana zależność jest opcjonalna i nie wydarzy się nic złego, jeśli jej nie dostarczymy.

Jeszcze jeden krok do sukcesu, tym razem po stronie użytkownika, my swoją robotę wykonaliśmy 🙂

Aby użytkownik mógł skorzystać ze swojego obiektu konfiguracyjnego, który jest zależnością komponentu FileUploaderComponent, to musi go dostarczyć na poziomie np. głównego modułu i zarejestrować go w tablicy providers:

Czyli dostarczyliśmy zależność FILE_UPLOADER_GLOBAL_CONFIG, która po wstrzyknięciu będzie obiektem { multiple: false }.

Jeśli jest dla Ciebie nowością pole useValue, to już wyjaśniam! useValue, po prostu podmieni nam zależność na przypisaną wartość. Oprócz useValue, istnieje również możliwość skorzystania w innych przypadkach np. z  useClass, które jest bardzo przydatne podczas mockowania serwisów w testach.

Link do przykładu:
https://stackblitz.com/edit/angular-h5qadz?file=app/file-uploader-global-config.token.ts

Tyle na dziś, miłego! 🙂

ps! Partner społeczny bloga, szkolenia Angular In Space, wkrótce (21-23 marca), zawita do Gdańska. Jeśli czujesz potrzebę doszlifowania swoich umiejętności z Angulara, lub chcesz wysłać swojego pracownika / pracowników na profesjonalne szkolenie, to jest to idealna okazja. Więcej informacji:
https://angular-in-space.pl/rejestracja/2018-03-21

…a z hasłem angularlove przy zapisach, 10% żniżki! ; )

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.

2 komentarzy

  1. Tomek

    Mam pytanie… jeśli mam 1 moduł a w nim w kilku miejscach wstrzyknięty komponent który jako input przyjmuje config gdyż w zależności od use case’a renderuje różny content, czy taki przypadek nadaje się na injection token? jesli tak to w jaki sposób nadpisywać config zdefiniowany w app.module ?

    • jeśli dobrze Cię zrozumiałem, to w Twoim przypadku użycie @Input jest bardziej odpowiednie. Injection Token będzie dobry jeśli ta konfiguracja jest dostarczona poprzez konstruktor. W takiej sytuacji dostarczasz konfigurację jako token w tablicy providers.

Dodaj komentarz

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