Angular – w świecie tworzenia aplikacji typu SPA (Single Page Application) to jeden z trzech najpopularniejszych narzędzi (razem z React i Vue). Został stworzony przez Google, który również jest twórcą AngularJS – biblioteki, która parę lat temu była również bardzo popularna. Angular w przeciwieństwie do AngularJS, jest napisany w TypeScript oraz jego struktura jest kompletnie nowa.
Angular jest rozbudowanym narzędziem, posiada szereg funkcjonalności, które umożliwiają napisanie kompletnej aplikacji Frontend. Zrozumienie pewnych elementów jest kluczowe, żeby móc świadomie przy jego użyciu tworzyć aplikacje. Tymi elementami są komponenty, moduły i serwisy.
Komponent
Komponent jest to element, z którego buduje się wygląd aplikacji oraz obsługę interakcji z użytkownikiem. Aplikacja jest budowana komponentami w sposób hierarchiczny. Oznacza to, że aplikacja startowana jest od jednego komponentu, tzw. Root Component, na którym osadzone są kolejne komponenty, a w nich jeszcze następne.
Komponent Angularowy składa się z trzech części: klasy, szablonu (ang. template) i z pliku ze stylami.
Klasa
Klasa używana jest do określenia logiki komponentu, reakcji na zdarzenia. Bez dekoratora @Component Angular nie uzna, że dana klasa jest klasą komponentu. Dekorator dostaje konfigurację, która determinuje ustawienia komponentu, m.in., jakie części komponentu wchodzą w tego skład:
- templateUrl – ścieżka do szablonu komponentu,
- styleUrls – ścieżki do plików ze stylami, opcjonalna properta,
- selector – oznaczenie, pod jaką nazwą komponent będzie osadzany w innych komponentach.
Szablon
W szablonie (ang. template) jest zawarty kod HTML, który opisuje, z jakich elementów DOM i komponentów zbudowany jest dany komponent.
Jest to plik ze zwykłym kodem HTML z dodatkami od Angulara. Jednym z dodatków jest możliwość osadzania komponentów przy pomocy selektora przekazanego w konfiguracji.
Plik ze stylami
W pliku/plikach ze stylami znajduje się kod CSS bądź kod preprocesora CSS. Każdy komponent, który ma w konfiguracji oznaczoną ścieżkę do pliku ze stylami „widzi” zawarty w nim kod.
Aplikacja napisana w Angularze może też posiadać globalne pliki ze stylami, widoczne dla wszystkich komponentów.
Moduł
Moduł, w przeciwieństwie do komponentu, składa się jedynie z klasy. Moduły hermetyzują struktury osadzone w projekcie, w taki sposób żeby programista miał kontrolę nad tym, co jest widoczne a co nie dla poszczególnych elementów.
Co najmniej jeden moduł musi się znajdować w aplikacji. Przyjęło się, że taki moduł nazywany jest AppModule.
Jeżeli przed klasą znajduje się dekorator @NgModule wtedy Angular wie, że dana klasa jest modułem. Moduł posiada następującą konfigurację:
- declarations - komponenty działające w ramach modułu,
- imports - importowanie innych modułów, które są wymagane do działania elementów tego modułu,
- bootstrap – określenie, który komponent ma się uruchomić po wystartowaniu aplikacji, tzw. Root Component.
Aplikacja może posiadać więcej niż jeden moduł. W jakich przypadkach przydaje się tworzyć więcej niż jeden moduł? Kiedy aplikacja rozrasta się i nie chcemy tworzyć jednego, wielkiego, nieczytelnego modułu. Wówczas możemy stworzyć tzw. Feature Modules, czyli moduły tworzone per funkcjonalność. Jest jeszcze jeden ważny powód tworzenia takich modułów – lazy loading modułów. Zachęcam do zgłębienia tematu w dokumentacji Angulara.
Konfiguracja Feature Module różni się od AppModule dwiema propertami:
- posiada propertę exports – komponenty, które będą mogły być widoczne w ramach innego modułu, który zaimportuje ten moduł. Np., gdy AppModule zaimportuje ParentModule, wtedy komponenty osadzone w declarations AppModule będą mogły używać komponentów ParentComponent i ChildComponent,
- nie posiada property bootstrap, ponieważ tylko jeden moduł może być modułem głównym, z którego startuje aplikacja.
Niekiedy zachodzi potrzeba, żeby Feature moduły korzystały ze współdzielonych komponentów. Komponent raz przekazany do property declarations konfiguracji modułu nie może być przekazany do konfiguracji innego modułu. Co w takim przypadku zrobić? Stworzyć moduł, który będzie miał współdzielone komponenty i będzie je eksportował. Przyjęło się, że taki moduł nazywany jest SharedModule. Ma on dokładnie taką samą konfigurację jak Feature Module.
Serwis
Każda aplikacja Frontend służy do tego żeby prezentować dane w miłej dla oka formie. Zatem potrzebna jest struktura, która będzie zarządzać danymi w obrębie całej aplikacji. Taką strukturą jest serwis.
Instancje serwisów są tworzone przez wbudowany w Angulara mechanizm – wstrzykiwanie zależności (ang. Dependency Injection). Angular wstrzykuje zależności przez konstruktor. Jeżeli dekorator @Injectable ma przekazaną konfiguracje providedIn z wartością „root” mechanizm wstrzykiwania zależności stworzy singletona i przekaże go do każdego obiektu.
Jeżeli komponent potrzebuje odrębnej instancji to można tego dokonać przekazując klasę serwisu do konfiguracji komponentu przez propertę providers.
Należy mieć na uwadze, że taka osobna instancja nie tylko będzie przekazywana do docelowego komponentu, ale także do komponentów, które w danym komponencie są osadzone, czyli do komponentów dzieci.
Dobrą praktyką jest także umieszczanie logiki biznesowej w serwisach. Dzięki temu komponenty mogą korzystać z logiki bez kopiowania jej do wnętrza klas komponentu. W ten sposób nie trzeba dbać o poprawność kodu w paru komponentach. Co więcej komponenty są bardziej czytelne, bo mają mniej kodu.
Podsumowanie
Artykuł opisuje trzy struktury, z których składa się Angular: komponent, moduł, serwis. Z komponentów buduje się aplikacje. Moduł grupuje komponenty i inne struktury. Serwis odpowiedzialny jest za zarządzanie danymi oraz współdzielenie logiki biznesowej między komponentami.
Angular jest rozbudowanym narzędziem. Znajomość tylko powyższych elementów nie wystarczy do napisania kompletnej aplikacji SPA. Do dalszej nauki polecam zapoznać się ze szkoleniem umieszczonym w dokumentacji Angulara.
Ewelina Olejnik