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.

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

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *