Szkolenie poprowadził Tomasz Sułkowski - developer pracujący w Hexagram. Od 16 miesięcy związany z firmą konsultingową Sages.
Miejsce szkolenia to siedziba firmy Sages na ul. Nowogrodzka 62c. Więcej o firmie: sages.com.pl/.
Slajdy dostępne pod adresem: slideshare.net/sagespl/podstawy-angularjs.
09:05 - Agenda
- wprowadzenie / kontekst / narzędzia
- teoria / demo
- warsztat
- teoria / demo
- warsztat
- ...
- Q & A
Korzystamy ze Slacka - IMO komunikator teraźniejszych czasów.
Na początku trochę pytań odnośnie doświadczeń.
Cel: Budujemy aplikację typu SPA
SPA - Single Page Application
Nawigacja w aplikacji typu SPA polega na żonglowaniu hashem w URLu.
Narzędzia
Tomek polecał narzędzia:
- WebStorm (IDE)
- Sublime Text 3
- Atom 1.0
- Brackets
- ... Vim?
Ze swojego doświadczenia stwierdził, że po kilku miesiącach korzystania z Submlime Text 3, postanowił przerzucić się na WebStorm, ze względu na lepsze podpowiadanie oraz na poprawianie literówek, które każdy z nas, siłą rzeczy, popełnia.
npm - Node Packaged Modules
- system zarządzania zależnościami dla "server-side js"
- zależności opisywane w pliku
package.json
npm install
- instaluje pakiety, których jeszcze nie ma w projekcienpm update
- sprawdza, czy istnieją nowsze wersje pakietów + instalujenpm install nazwa-pakietu --save-dev
- instaluje pakiet, dodaje go dopackage.json
Aby nie trzymać zależności w projekcie. Dla nowego środowiska wystarczy zainstalować jednym poleceniem biblioteki.
Dodatkowo, możemy określi konkretną wersję którą chcemy zainstalować.
Domyślnie, trzeba by było szukać biblioteki w sieci i ściągać plik na dysk - teraz wystarczy jedno polecenie.
Bower
Instalacja poleceniem npm install -g bower
- zarządzanie zależnościami dla "client-side js"
- zależności opisywane w
bower.json
bower install
- instaluje pakiety, których jeszcze nie ma w projekciebower update
- sprawdza, czy istnieją nowsze wersje pakietów + instalujebower install nazwa-pakietu --save
- instaluje pakiet, dodaje go dobower.json
- pakiety instalowane są do katalogu
/bower_components/nazwa-pakietu/...
- stamtąd należy je linkować w plikach html
09:30 - Ćwiczenie 1
Stworzenie nowego projektu w WebStorm.
- ctrl+shift+a - wyszukiwarka wszystkich opcji edytora WebStorm
- ctrl+shift+o - szukanie plików w projekcie
- ctrl+e - lista ostatnio otwartych plików
Złota myśl Nauka skrótów jest bardzo pomocna. Umiejętność sprawnego poruszania się w skrótach, pomaga zdecydowanie zmniejszyć czas potrzebny na wykonywanie bieżącej pracy.
Omawianie struktury wygenerowanego seed-a
Kiedy stworzyliśmy nowy projekt typu AngularJS WebStorm stworzył prostą strukturę katalogów wraz z wieloma plikami.
W kolejnym kroku czyścimy boilerplate usuwając e2e-test, index_async.html oraz 2 pliki CSS z html5-boilerplate.
Po wydaniu magicznego polecenia npm install
mamy do projektu ściągnięte wszystkie zależności.
W pliku package.json
w script/postinstall
uruchomimy również bower install
,
więc i biblioteki client-side będą zainstalowane w katalogu app/bower_components
.
Gdybyśmy nie mieli żadnego serwera serwującego statyki, w zależnościach mamy wpisany http-server
.
Jest to prosty serwer napisany w Node.js
.
10:00 - Instalujemy Bootstrap
Dzięki poleceniu bower install --save bootstrap
instalujemy Bootstrap-a.
W zależności Bootstrap jest biblioteka jQuery.
W katalogu app/bower_components
znajduje się ściągnięty pełny projekt Bootstrap oraz jQuery.
TIP: Bower zawsze cache-uje sobie biblioteki, aby przy ponownym pobraniu szybko ściągnął kolejny raz zależności.
10:04 - Korzystamy z Bootstrap-a
Dołączamy Bootstrap-a do index.html dorzucając przed plikiem app.css
następującą linijkę kodu:
Usuwanie zbędne paczki: bower uninstall angular-mocks
.
Dodatkowo usuńmy zbędne komponenty app/components
.
10:11 - Prezentacja docelowej aplikacji
Tomek przedstawia aplikację, do którą chcemy dziś napisać. Portal bardzo podobny do ipla.tv lub może bardziej do filmweb.pl. Przeglądanie listy seriali i wchodzimy w szczegóły danego serialu i możemy przeczytać opis. Możemy wyszukiwać dany serial po nazwie, oraz dodać dowolny serial do listy ulubionych.
10:15 - AngularJS
Posłuchamy teraz trochę więcej na temat samej biblioteki AngularJS
.
Najbardziej zewnętrzną rzeczą w aplikacji jest moduł.
Każdy moduł może posiadać specyficzną konfigurację.
Na szkoleniu będziemy korzystali z jednej specyficznej usługi - routing (ui.router
).
TIP: Podejście Fat model ma do siebie, że kontrolery powinny być "cienkie", czyli nie zawierały dużo kodu, ale za to modele powinny przechowywać jak najwięcej się da 😄
Moduły, struktura aplikacji
Form Follows Function- Moduły wskazuję na zależności od zewnętrznych bibliotek
- Modułu nie separują zawieranych komponentów (brak namespaces)
- Poszczególne fragmenty aplikacji jako moduły, o hierarchii odzwierciedlonej w strukturze katalogów
TIP: Gdy stworzymy usługę o tej samej nazwie, to zostanie nadpisana poprzednia usługa w innym module o tej samej nazwie.
Routing
ngRoute
do jakiegoś czasu był obecny w AngularJS. Jest dosyć prosty.
Lepszym rozwiązaniem jest ui.router
.
W ui.router
mamy kaskady widoków - każdy widok (kawałek HTMLa) może posiadać dostęp
do innego kawałka kodu HTML, bez przeładowania całego globalnego widoku.
ngRoute
niestety przeładowuje całą stronę, dzięki czemu korzystanie z aplikacji jest bardzo podobne
do typowego przeglądania stron internetowych (mam tu na myśli efekt przeładowania się całej strony).
10:33 - Ćwiczenie 2
Podmiana ngRoute
na ui.router
(github.com/angular-ui/ui-router).
Instalujemy ui.router
poprzez wykonywanie polecenia:
bower install angular-ui-router --save
oraz usuwamy starą paczkę
bower uninstall angular-route --save
11:04 - Ścieżki w aplikacji (ui.router)
Dodajemy katalogi: app/library
, app/profile
, app/search
.
11:12 - Dependency Injection
AngularJS zanalizuje kontrolery, wyciąga nazwy parametrów na podstawie łańcucha znaków,
który dostajemy kiedy uruchomimy toString
na funkcji.
Na podstawie wyrażenia regularnego AngularJS wyciąga nazwy parametrów, których oczekujemy.
TIP: Gdy dokonamy minifikacji kodu pojawi się problem
ze wstrzykiwaniem odpowiednich modułów, ponieważ wszystkie
nazwy zmiennych zostaną zmienione na krótkie zaczynając od zwykłych liter.
Z pomocą przychodzi ngAnnotate
-
github.com/olov/ng-annotate.
Dodajemy moduł ui.router
.
Dodatkowo podmieniamy w index.html
Tworzymy strukturę w projekcie - plik app/search/search.html
.
Ustawiamy domyślną stronę poprzez $urlRouterProvider
11:49 - Widok
Kawałki mniejszego HTMLa, które możemy użyć w innym (większym).
11:51 - Controller
Zwykła funkcja JavaScript.
Powiązanie z widokiem odbywa się przez $scope
.
TIP: $scope
jest to usługa, która jest obiektem to,
co zdefiniujemy w tym obiekcie, będzie to od razu dostępne dla widoku (dyrektywy).
11:54 - Dyrektywy
... czyli HTML na sterydach! 😄
Możemy użyć na kilka sposobów:
- element
- atrybut
- klasę CSS
- komentarz
Wbudowane dyrektywy:
ng-app
ng-init
- służy do wykonywania kodu na początkung-model
- służy do prowadzenia interakcji między użytkownikiem a modelemng-show
- gdy wartość będzie truly to kontener się wyświetli (dodaje klasę ng-hide - widoczność poprzez CSS)ng-if
- usuwa albo dodaje dany fragment do DOMang-repeat
- służy do iteracji po tablicyng-list
- podczas prezentacja tablicy jako ciąg znaków, traktuje ten ciąg jako tablicę
two-way data-binding - wiązanie w obie strony, tj: widok aktualizuje model,
który od razu jest zmieniony w kontrolerze, ale i w drugą stronę, gdy kontroler zaktualizuje model,
będzie od widoczny (najszybciej jak to możliwe) widoku.
Więcej na ten temat na stronie https://docs.angularjs.org/guide/databinding.
TIP: AngularJS promuje deklaratywny styl pisania aplikacji (przeciwieństwo do imperatywnego).
Logika interfejsu jest w HTMLu!
Input jest dyrektywą!
Więcej na temat dyrektyw w dokumentacji: https://docs.angularjs.org/guide/directive.
TIP: Podczas wykonania ng-repeat
tablica
nie może posiadać duplikatów.
Jeśli jednak chcemy operować na duplikatach trzeba utworzyć specjalną konstrukcję:
12:18 - Usługi
Do czego służą usługi?
Miejsce gdzie trzymamy logikę biznesową. Wykonują się w kilku kontrolerów, więc nie ma sensu tego powtarzać. Usługi również służą do tego, aby współdzielić dane miedzy kontrolerami.
Definicja usług na 5 sposobów:
.constant()
- proste wartości, nie można nadpisywać.value()
- proste wartości, można nadpisywać.service()
- większa usługa, która może posiadać wiele metod i właściwości.factory()
- większa usługa, która zwraca jeden obiekt.provider()
- generyczna usługa, bo każda jest de facto providerem
Więcej na temat usług https://docs.angularjs.org/api/ng/service/$http.
12:35 - Ćwiczenie 3
Tworzymy SearchController
w katalogu app/search/
,
wykorzystujemy usługę $http
do pobierania listy filmów.
13:07 - Przerwa obiadowa!
14:05 - Prezentacja swoich wyszukiwarek
Rozwiązujemy problem z obrazkami poprzez ng-src
.
14:33 - Tworzymy service
Bardzo prosty service
operujący na kolekcji dodanych elementów. Przykładowa implementacja:
Jako dodatkowe zajęcie dostałem zapisywanie do localStorage
. Udało mi się zrobić w 5 minut 😄
Tomasz poleca portal nodeschool.io/pl/ gdzie można podszkolić się z JavaScript.
Aby obserwować jakiś model należy wykonać:
Na samym początku ładowania aplikacji $watch
zostanie uruchomiony i przekazane zostaną mu wartości undefined
.
Można się przed tym zabezpieczyć wystarczy sprawdzić czy nowa wartość równą się starej, bo tylko na początku obie wartości będą miały
tą samo wartość.
15:22 - Dyrektywa ng-model-options
Dzięki tej dyrektywie mamy możliwość skonfigurowania komunikacji pomiędzy widokiem a kontrolerem.
Dzięki takiemu zastosowaniu odciążamy trochę aplikację, dodając lag na zmianę modelu.
Tomasz poleca wtyczkę do Batarang
, dzięki której mamy możliwość podglądu modelów analizując DOMa.
15:30 - Directive Definition Object
- Enkapsulują logikę związaną z zachowaniem
- Tworzą widgety - małe aplikacje, klocki z których budujemy większe fragmenty
Jako zadanie domowe warto zrobić dyrektywę dla przycisków "Dodaj" i "Usuń".
16:25 - Filtry
Umożliwiają przekształcanie danych w trakcje przejścia ze $scope
do widoku bez zmieniania oryginalnej wartości.
Jest około 7 standardowych filtrów. Ta mała liczba wynika ze względu na prostotę dodawania swoich.
Od AngularJS 1.3 mamy w filtrach pure function
, czyli dla takich samych parametrów mamy te same wyjście, tym samym
biblioteka zapamiętuje (proces memoizacja) wynik dla tych samych parametrów.
16:39 - Formularze
TIP: Koniecznie trzeba ustawiać nazwy dla znacznika form,
ponieważ będzie on pod tą nazwą dostępny w scope
.
Stany formularza
$valid
- bez błędów$invalid
- z błędami$pristine
- nienaruszony$dirty
- zmodyfikowany
16:57 - Dobre praktyki
17:08 - Kończymy na dziś!
Podziękowanie dla Tomka za całodniowe szkolenie 😄