[PL] Kurs Angular na Steemit #2 /Na początku był chaos/
polish·@jakipatryk·
0.000 HBD[PL] Kurs Angular na Steemit #2 /Na początku był chaos/
<sub>// for my non-polish readers: this is just a polish translation of <a href="https://steemit.com/utopian-io/@jakipatryk/cbac-2-at-the-beginning-there-was-chaos">this article</a></sub> **Celem tego artykułu jest przekazanie wiedzy oraz jej źródeł, które pozwolą Ci rozpocząć tworzenie prostych aplikacji, z których kodem nikt prawdopodobnie nie będzie chciał pracować. Nie, nie jestem pijany.** https://res.cloudinary.com/hpiynhbhq/image/upload/v1514491385/vziehbsovjhluma7y9fr.png # Poczekaj, co? No może nie jest to najlepszy opis intencji, którymi się kierowałem. Tak, ten tutorial nie uczyni Cię mistrzem Angulara, który będzie pisał kod najwyższej jakości, ale zdecydowanie ten wpis wraz z dołączonymi linkami powinien powinien dostarczyć wystarczającą widzę aby **zacząć bawić się Angularem oraz Firestore** (jeśli nie czytałeś [poprzedniej części kursu](https://steemit.com/utopian-io/@jakipatryk/pl-angular-od-zera-kurs-oparty-o-spolecznosc-ustawiamy-projekt), zachęcam do zrobienia tego teraz). Głębsze wytłumaczenie koncepcji z grubsza opisanych teraz znajdzie się w kolejnych wpisach. Właśnie, **linki**. Nie da się ukryć, że najpopularniejszym językiem w IT jest język angielski. Nie chcę teraz się o tym rozpisywać, ale efektem tego jest to, że artykuły, prelekcje i dokumentacje, które polecam sprawdzić po przeczytaniu tego artykułu, są po angielsku. Nie da się tego przeskoczyć. Jednak zanim przejdziemy do kodu projektu aplikacji zarządzającej zadaniami, musimy przyjrzeć się językowi programowania, którego będziemy używać. ## TypeScript > Ale jak to, w wymaganiach do tego kursu była znajomość JavaScript, a ty mi wyskakujesz z jakimś TypeScript <sub>każdy</sub> ### Czym jest TypeScript? Wystarczy o tym myśleć jak o potężniejszym JavaScripcie. Na koniec i tak się kompiluje do JSa, ponieważ jest tylko jego **nadzbiorem**. Czemu więc powinniśmy tego używać? Najważniejszą różnicą jest to, że TS jest **silnie typowany**, czyli możemy określić typ (*string*, *number*, itp.) zmiennej lub tego, co ma być zwrócone z funkcji przy ich deklaracji. Jest to jednak opcjonalne, nic nie stoi na przeszkodzie, aby wciąż używać dynamicznego typowania, ale stracimy wtedy możliwość unikania pewnych błędów jeszcze podczas pisania kodu... i Angular team używa TypeScript wraz z silnym typowaniem ;) ### Jakie elementy TypeScript powinieneś znać? Będę teraz szczery - jest ich mało. TS sam w sobie jest bardzo potężnym narzędziem, ale w tym kursie będziemy używać tylko paru jego elementów. Pozostały kod to tak naprawdę JavaScript (w tym najnowsze wersje **ES6** i **ES7**, tak, kompilator TypeScript radzi sobie również z nimi). Co więc powinieneś potrafić? - **typy** jak już wcześniej wspomniałem, w TS możemy deklarować zmienne i funkcje określając jednocześnie ich typ, na przykład jeśli chcemy aby zmienna <code>numberOfTasks</code> była liczbą, możemy jej używać w następujący sposób: https://res.cloudinary.com/hpiynhbhq/image/upload/v1513623750/xp3nuaur7kfkk4jmjpts.png - **klasy** właśnie z nich zbudowana jest większość elementów Angulara, których będziemy używać. Okazuje się, że klasy w TS działają analogicznie do tych znanych z innych języków programowania, jak np. C#. Są one dodatkowo **bardzo podobne** do klas znanych ze składni **ES6**, jednak wprowadzają dodatkowo obsługę modyfikatorów dostępu (domyślnie <code>public</code>, można też używać <code>private</code> oraz <code>protected</code>, po więcej informacji zapraszam oczywiście do sekcji linków). https://res.cloudinary.com/hpiynhbhq/image/upload/v1513623935/xzvtfielclzhlsrzeq0d.png jest parę **sztuczek**, których będziemy używać, na przykład zamiast pisać konstruktor taki jak na przykładzie powyżej, możemy zapisać go skrótem: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514044077/wtfvodua3kpfaeinbs1e.png taki konstruktor utworzy właściwość publiczną klasy <code>name</code> oraz przypisze do niej wartość otrzymaną przy inicjalizacji obiektu na podstawie tej klasy. - **interfejsy** silne typowanie jest świetnym narzędziem, ale co jeśli zmienna ma być obiektem określonego typu? Możemy w takiej sytuacji zdefiniować interfejs: https://res.cloudinary.com/hpiynhbhq/image/upload/v1513624103/q1b2moypjgwghm9gch9b.png interfejsy są ograniczone w stosunku do klas, nie można ich na przykład **zainicjalizować** (za pomocą słowa kluczowego <code>new</code>), nie mogą **implementować logiki**. Dlaczego jednak powinniśmy ich używać? Ponownie, zapraszam do zapoznania się z sekcją linków. # Podstawowe elementy Angulara Spójrzmy na strukturę plików projektu (kod jest dostępny [Githubie](https://github.com/jakipatryk/angular-todo-list-tutorial/tree/tutorial-part-2)): https://res.cloudinary.com/hpiynhbhq/image/upload/v1513599250/zbbq3qigv3gh1hterdmc.png Całkiem sporo plików i folderów, co? Mam dla Ciebie dobrą wiadomość - większością **nie musisz się przejmować** (przynajmniej na tym etapie nauki). To, czego potrzebujesz znajduje się w folderze **src**: https://res.cloudinary.com/hpiynhbhq/image/upload/v1513599506/ro8ys5lat1puowmsqnjv.png - jaki jest pierwszy plik serwowany klientowi odwiedzającemu stronę internetową? Tak, *index.html*: https://res.cloudinary.com/hpiynhbhq/image/upload/v1513602615/mywgls5jtw0zwmyvwkhw.png jednak jako użytkownicy **Angular CLI** możemy usiąść pod palmą i cieszyć się tworzeniem logiki i widoków aplikacji bez większych zmartwień o ten plik - CLI doda tu wszystkie potrzebne pliki w czasie budowania projektu. - nie będziesz pewnie zdziwiony również, jeśli powiem, że flik *styles.scss* definiuje style naszej aplikacji. Należy jednak pamiętać, że są to **style globalne**: https://res.cloudinary.com/hpiynhbhq/image/upload/v1513604447/r2s9sxletywd0abfsyij.png różnica między tymi stylami a stylami lokalnymi będzie dla Ciebie intuicyjna, gdy przedstawię komponenty - kolejnym plikiem kluczowym dla CLI i dosyć bezużytecznym dla nowicjusza jest*main.ts*: https://res.cloudinary.com/hpiynhbhq/image/upload/v1513605201/tz3zk0enxcwvhtqcspek.png jest to punkt początkowy aplikacji. **Ładuje on moduł główny** (AppModule) projektu. Zazwyczaj nie musisz tu nic zmieniać. - *assets* jest folderem, w którym powinieneś przechowywać takie pliki, które podczas budowania projektu mają zostać w takim stanie, w jakim są, np. obrazki - *environments* to folder, w którym przechowujemy zmienne konfiguracyjne, takie jak np. *firebaseConfig* który dodaliśmy w poprzedniej części kursu - ***app*** jest folderem, w którym będziemy wykonywać główną część naszej pracy. Zawiera wszystkie **moduły**, **komponenty**, **serwisy**, **dyrektywy**, **pipe'y**, itd. Będziemy mieć tu sporo zabawy. ## Komponenty https://res.cloudinary.com/hpiynhbhq/image/upload/v1513613845/yvkmrg8igaibcrrhz6rv.png Komponent jest elementem Angulara, którego będziesz używać najczęściej. Upraszczając, odpowiadają one za część aplikacji, której zadaniem jest kontrola **widoków**, czyli **interakcji** z użytkownikiem. Każdy komponent składa się z następujących elementów: - dekorator **<code>@Component()</code>** - jest używany aby poinformować kompilator, że klasa następująca po nim jest komponentem. Przyjmuje on pewne opcje konfiguracyjne, np: - <code>selector</code> - ta opcja określa znacznik, jaki będzie miał ten komponent. Selector w naszym AppComponent to *app-root*, więc kiedykolwiek Angular znajdzie <code><app-root></app-root></code> w szablonie komponentu, który jest **wyżej w drzewku komponentów** (tzn. jest przynajmniej jego rodzicem), dodaje w to miejsce AppComponent. Już widzieliśmy ten znacznik - w *index.html*. Dokładnie, **AppComponent jest głównym komponentem** (najwyższy w drzewku) naszej aplikacji, więc gdy będziemy w przyszłości dodawać inne komponenty, to właśnie w jego szablonie będziemy umieszczać ich znacznik. - <code>templateUrl</code> - ścieżka do szablonu komponentu, można zamiast tego użyć <code>template</code> i szablon umieszczać bezpośrednio w pliku *.ts*, jednak wtedy kod może stać się nieczytelny - <code>styleUrls</code> - lista ścieżek do plików *.scss* komponentu (**style lokalne**) - **<code>export class ComponentNameComponent {}</code>** - tu umieszczasz logikę komponentu. Możesz tu robić wszystko to, co umożliwia TypeScript. Dodatkowo zarówno metody jak i właściwości tu zdefiniowane mogą być użyte przez szablon komponentu Używanie komponentu bez **szablonu** nie miałoby zbyt dużego sensu, to tu dzieje się magia: https://res.cloudinary.com/hpiynhbhq/image/upload/v1513619234/zzly6eyqpmsn7cqr2exo.png ### Przepływ danych Wymiana informacji pomiędzy aplikacją a użytkownikiem (i w przeciwną stronę) jest kluczowa w nowoczesnych aplikacjach internetowych. Jak jest osiągana w Angularze? Jestna to pare sposobów: - **wyświetlanie danych (z klasy do szablonu):** powiedzmy, że mamy zmienną <code>name</code> w klasie komponentu. Aby wyświetlić jej wartość w szablonie wystarczy dodać w dowolnym miejscu szablonu <code>{{ name }}</code> (jest to nazywane **string interpolation**), a Angular znajdzie odpowiednią właściwość w klasie i zastąpi to miejsce jej wartością. - **property binding (z klasy do szablonu):** a co jeśli chcielibyśmy, aby np. dany element HTML w szablonie wyświetlał się tylko gdy właściwość <code>display</code> w klasie komponentu ma wartość *true*? Jedną z możliwości jest modyfikowanie właściwości *hidden*elementu HTML, ale jak ją powiązać ze zmienną z klasy? Angular sprawia, że jest to proste: <code><jakis-element [hidden]="display">Jeśli display to false, nie będzie mnie widać!</jakis-element></code> Możemy w ten sposób działać nie tylko na natywnych elementach HTML, ale także na **dyrektywach**. - **event binding (z szablonu do klasy):** obie powyższe metody pozwalały na przepływ danych w jedną stronę, od klasy do szablonu. Aby przekazywać dane w odwrotną stronę, czyli od użytkownika do aplikacji, możemy użyć event bindingu <code><button (click)="deleteAccount('jakipatryk')">Usuń konto</ button></code> w powyższym przykładzie wywołujemy metodę <code>deleteAccount()</code> i przekazujemy jej wartość "jakipatryk" za każdym razem, gdy użytkownik kliknie ten przycisk - **two-way data binding** zdarza się, że chcemy połączyć przepływ danych w obie strony, możemy to zrobić na skróty: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514049238/wlttqj1r9oovn5aptwlq.png okazuje się, że podczas wpisywania przez czegokolwiek w <code>input</code> z powyżeszego przykładu, aktualizowana jest także wartość w miejscu <code>{{itemName}}</code>. ### Dyrektywa *ngFor Załóżmy, że masz tablicę <code>itemsArray</code> składającą się z obiektów typu Item. Każdy jej element ma właściwości <code>name</code> i <code>type</code>. Jak to wyświetlić w szablonie komponentu w prosty sposób? Dzięki wbudowanej dyrektywie **NgFor** jest to możliwe: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514049396/teapbii1muy419lfebuz.png jak widzisz, **iterujemy** po tablicy <code>itemsArray</code> i nazywamy **każdy jej element** <code>item</code>. Angular wyrenderuje tyle div'ów ile jest elementów w tablicy i wypełni każdy z nich danymi danego elementu używając *string interpolation*. ## Serwisy https://res.cloudinary.com/hpiynhbhq/image/upload/v1514049703/qk7eeocj6rakvwsfcc8w.png > Component classes should be lean. They don't fetch data from the server, validate user input, or log directly to the console. They delegate such tasks to services. <sub>źródło: <a href="https://angular.io/guide/architecture#services">dokumentacja Angulara</a></sub> Serwisy są bardzo ważne. Teoretycznie większość tego, co tam się pisze, może być napisane w klasie komponentu. Jest to jednak podejście **bardzo ograniczone**. Angular używa pewnej techniki, znanej jako **dependency injection** (wstrzykiwanie zależności) aby przekazać komponentom instancje serwisu, jakiej potrzebują. W serwisy i technikę *dependency injection* zagłębimy się w następnej części kursu. ## Moduły Zdaje się, że już słyszałeś o Angularowych modułach (nie mylić z JavaScriptowymi) - w pliku *main.ts* zdefiniowany jest moduł główny projektu - moduł, który jest ładowany na starcie aplikacji. Naszym głównym modułem jest oczywiście **AppModule**: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514221234/kq5vslgiezidhp9wy95c.png Dekorator <b><code>@NgModule()</code></b> także przyjmuje pewne opcje konfiguracyjne: - <code>declarations</code> - umieszczane są tutaj wszystkie komponenty, napisane przez nas dyrektywy i pipe'y, których będziemy chcieli użyć w obrębie tego modułu (zasięg modułów będzie opisany w dalszej części kursu) - <code>imports</code> - jeśli dany moduł potrzebuje do działania innego modułu, np. jego serwisów bądź komponentów, tutaj właśnie go dodajemy - <code>providers</code> - brzmi jak świetne miejsce do umieszczania serwisów (no nie zawsze, ale zazwyczaj tak, więcej o tym w następnym wpisie) - <code>bootstrap</code> - Angular powinien wiedzieć, który komponent jest tym głównym w danym module, a to jest całkiem dobre miejsce aby go określić Dodawanie tego wszystkiego ręcznie byłoby zdecydowanie męczące, a **programista nie lubi się męczyć**. Całe szczęście, że mamy Angular CLI, który prawidłowo używany po raz kolejny zaoszczędzi nam mnóstwo czasu. Musisz jednak **uważać**. Jeśli generujesz za pomocą CLI np. komponent, to jest on automatycznie dodawany do AppModule (gdy mamy więcej niż jeden moduł nie koniecznie chcemy dodawać go akurat do AppModule), a jeśli generujemy serwis, domyślnie nie jest on nigdzie dodawany, więc musimy albo dodać go ręcznie albo zastosować flagę <code>--module ModułDoKtóregoChcemyDodaćSerwis</code> gdy go generujemy. W tym momencie mamy tylko jeden moduł, ale gdy projekt staje się bardziej rozbudowany należy nastanowić się nad zmianą tej architektury, ponieważ moduły dają nam potężne narzędzia do organizacji proejktu **i nie tylko**. Ale o tym kiedy idziej. # AngularFire2 Tak właściwie to więcej kodu już dziś nie będzie. Jednak nawet jeśli by zastosować taktykę kopiuj-wklej z Githuba projektu, aplikacja by **nie działała**. Musimy jeszcze wykonać parę czynności. Po pierwsze musimy zainstalowć poniższe zależności: <code>npm install angularfire2 firebase --save</code> [AngularFire2](https://github.com/angular/angularfire2) to oficjalna biblioteka do używania Firebase w Angularze. Jeśli czytałeś kod z *TaskService* to mogłeś zauważyć, że ta biblioteka jest tam używana - wszystkie operacje na **Firestore** są tam właśnie przez nią obsługiwane. No to teraz mamy zależności, ale... nie mamy **bazy danych** (Firestore). Należy więc ją utworzyć: 1. Otwórz [konsolę Firebase](https://console.firebase.google.com/) i wejdź do swojego projektu. 2. Nawiguj do **Database**. 3. Kliknij **TRY FIRESTORE BETA**: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514230023/pzxiku3tcrwmisungpyg.png 4. Wybierz **Start in test mode** i kliknij **enable**: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514230175/xutgznqwm2nvfwev6ojm.png Jesteśmy już blisko końca. Spróbuj zaserwować projekt (<code>ng serve</code>). Twoim oczom ukaże się **piękny czerwony błąd** w konsoli: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514230378/ystezjid1d5wedi7v0hn.png Na szczęście AngularFire2 ma odpowiednie narzędzia do obsługi tego błedu i jedyne co musimy zrobić to kliknąć na link zawarty w komunikacje błędu i kliknąć "CREATE INDEX": https://res.cloudinary.com/hpiynhbhq/image/upload/v1514230537/ojwtmjovukcxd3qvt6gd.png # Podsumowanie W tej części kursu Angulara przedstawiłem podstawy takich technologii jak TypeScript, Angular i Firestore, które zostały użyte do zbudowania prostej aplikacji do zarządzania listą zadań, która będzie w trakcie tego kursu rozwijana: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514230817/gtxr3cmcgkrp4mkng9vm.png wszystkie taski synchronizują się z **Google Cloud Firestore**: https://res.cloudinary.com/hpiynhbhq/image/upload/v1514230944/hs1oksvx8jo2nf37f25k.png Po przeczytaniu tego wpisu oraz treści zawartych w polecanych linkach, nie powinno być problemu z wykonaniem małych zmian w aplikacji kursowej lub nawet z utworzeniem prostej aplikacji od podstaw. # Linki, które warto sprawdzić: - TypeScript: - [Classes vs interfaces](https://toddmotto.com/classes-vs-interfaces-in-typescript) (Todd Motto) - [dokumendacja TypeScript](https://www.typescriptlang.org/docs/home.html) - [Angular: Why TypeScript?](https://vsavkin.com/writing-angular-2-in-typescript-1fa77c78d8e8) (Victor Savkin) - Angular: - podstawy Angulara w [oficjalnej dokumentacji](https://angular.io/guide/architecture) - [Reactive Programming in Angular](https://blog.nrwl.io/reactive-programming-in-angular-7dcded697e6c) (Victor Savkin) - [The Missing Introduction to Angular and Modern Design Patterns](https://medium.com/@sinedied/the-missing-introduction-to-angular-and-modern-design-patterns-43e8815c2801) (sinedied) - Firebase - [świetna prelekcja](https://youtu.be/puUqJTJVz5A?list=PLl-K7zZEsYLlTSrObc8GxDLarH7tF9WeW) (James Daniels i Erik Haddad) - [dokumentacja AngularFire2](https://github.com/angular/angularfire2/tree/master/docs/firestore) dla Firestore - [Firestore with AngularFire](https://youtu.be/-GjF9pSeFTs) tutorial <hr>
👍 jakipatryk, jamzed, noisy, jacekw, bolgan, aditor, curiosit, cwbrooch, osbielg, archerbest, m4rc3x, ruth-girl, saunter-pl, dww, openart, fervi, koltci, szymczok, go-away, raidho, astromaniak, avenal, firesteem, razex, piotrassnk, mys, rzezimioszek, hyubi, jcdent, ruta89, saunter, lukmarcus, planter, rozioo, patrycja, moreynas, miszorek, ceske.palivo,