Angular, cz. II - Instytut Informatyki Teoretycznej i Stosowanej

Transkrypt

Angular, cz. II - Instytut Informatyki Teoretycznej i Stosowanej
Angular, cz. II
Angular, cz. II
Tworzenie serwisów Web 2.0
dr inż. Robert Perliński
[email protected]
Politechnika Częstochowska
Instytut Informatyki Teoretycznej i Stosowanej
14 marca 2016
1/30
Plan prezentacji
1
Dyrektywy
ng-include
własne dyrektywy
2
Usługi
$scope
$http
Angular, cz. II
2/30
AngularJS
Strona projektu: https://angularjs.org/
Dokumentacja: https://docs.angularjs.org/api
Tutorial: https://docs.angularjs.org/tutorial
Przewodnik dla developerów: https://docs.angularjs.org/guide
Kurs na CodeSchool: http://angular.codeschool.com/
Angular, cz. II
3/30
Dyrektywy, ng-include
Dyrektywa ng-include:
pozwala zastąpić wielokrotnie powtarzający się fragment kodu
pozwala też na podzielenie większego kodu na mniejsze części
fragment kodu umieszczamy w osobnym pliku html i dołączamy
ng-include
może być wykorzystana jako dyrektywa użytkownika (atrybut src):
<ng-include src="">
...
</ng-include>
albo jako atrybut w dowolnym znaczniku:
<ANY ng-include="">
...
</ANY>
Angular napotykając ng-include wywołuje zapytanie AJAX.
Najpierw wczytywana jest cała strona, a następnie asynchronicznie
dołączane jej fragmenty.
Angular, cz. II
4/30
Dyrektywy, ng-include, przykład
Zawartość pliku index.html:
...
<h3>
{{produkt.nazwa}}
<em class="pull-right">{{produkt.cena|currency}}</em>
</h3>
...
Zawartość index.html po zmianie:
(dodatkowe apostrofy wewnątrz cudzysłowu - ng-include oczekuje zmiennych)
...
<h3 ng-include="’produkt-tytul.html’"></h3>
<h4 ng-include="sklep.nazwaPliku"></h4>
...
Zawartość produkt-tytul.html
{{produkt.nazwa}}
<em class="pull-right">{{produkt.cena|currency}}</em>
Angular, cz. II
5/30
Własne dyrektywy (ang. custom directives)
Dyrektywa ng-include działa ale ...
Preferowany sposób używania szablonów to tworzenie własnych
dyrektyw.
W dyrektywach użytkownika można używać dyrektyw wbudowanych,
np. ng-show.
Do własnych dyrektyw można, a nawet warto dołączać kontrolery.
Własna dyrektywa może wyglądać np.:
<produkt-tytul></produkt-tytul>
<h2 produkt-tytul></h2>
Własne dyrektywy do działania wymagają jednak dodatkowego kodu.
Dlaczego więc je używamy?
Angular, cz. II
6/30
Własne dyrektywy (ang. custom directives)
Dyrektywa ng-include działa ale ...
Preferowany sposób używania szablonów to tworzenie własnych
dyrektyw.
W dyrektywach użytkownika można używać dyrektyw wbudowanych,
np. ng-show.
Do własnych dyrektyw można, a nawet warto dołączać kontrolery.
Własna dyrektywa może wyglądać np.:
<produkt-tytul></produkt-tytul>
<h2 produkt-tytul></h2>
Własne dyrektywy do działania wymagają jednak dodatkowego kodu.
Dlaczego więc je używamy?
Pozwalają pisać kod html, który wyraża zachowanie naszej aplikacji.
Angular, cz. II
6/30
Własne dyrektywy wyrażają zachowanie aplikacji
Zwykle kod html pokazuje tylko strukturę, nie mówi nic o zachowaniu strony.
Własne dyrektywy pozwalają na wyrażenie tego, co dany fragment szablonu
robi (ekspresyjność, wyrazistość).
<aside class="col-sm-3">
<ksiazka-okladka></ksiazka-okladka>
<h4><ksiazka-ranking></ksiazka-ranking></h4>
</aside>
<div class="col-sm-9">
<h3><ksiazka-tytul></ksiazka-tytul></h3>
<ksiazka-autorzy></ksiazka-autorzy>
<ksiazka-opis></ksiazka-opis>
<ksiazka-rodzaj></ksiazka-gatunek>
</div>
Angular, cz. II
7/30
Własne dyrektywy - rodzaje
Dyrektywy rozwijające, włączające zdefiniowane szablony najprostszy rodzaj.
Definiuje się własny znacznik albo atrybut, który pokazuje albo rozwija
szablon.
Szablony takie mogą też zawierać kontroler czyli jakąś funkcjonalność
jeśli jest potrzebna.
Dyrektywy do wyrażania złożonych interfejsów użytkownika.
Dyrektywy do wywołujące zdarzenia i rejestrujące uchwyty do zdarzeń.
Dyrektywy pozwalające na wykorzystanie zdefiniowanych
komponentów.
Angular, cz. II
8/30
Definiowanie własnej dyrektywy I
Dyrektywa <produkt-tytul></produkt-tytul> wymaga następującej
definicji:
app.directive(’produktTytul’, function(){
return {
restrict: ’E’,
templateUrl: ’produkt-tytul.html’
};
});
app.directive(); - dyrektywy w Angular.
Pierwszy argument to nazwa dyrektywy.
Myślinik w nazwie w HTML zmienia się na dużą literę w nazwie JavaScript.
Drugi argument to anonimowa funkcja, ktora zwraca obiekt definiujący
dyrektywę (ang. directive definition object).
Obiekt definiujący dyrektywę to, najprościej mówiąc, konfiguracja
określająca jak dyrektywa ma działać.
Angular, cz. II
9/30
Definiowanie własnej dyrektywy II
Dyrektywa <produkt-tytul></produkt-tytul> wymaga następującej
definicji:
app.directive(’produktTytul’, function(){
return {
restrict: ’E’,
templateUrl: ’produkt-tytul.html’
};
});
Dwie opcje konfiguracyjne:
restrict - określa typ dyrektywy. ’E’ od słowa ’Element’ czyli
dyrektywa będzie nowym elementem HTML.
templateUrl - zawiera URL szablonu, który chcemy pozwiązać z
definiowaną dyrektywą.
Dyrektywę definiujemy wewnątrz modułu, np. w pliku app.js.
Unikamy samoamkniętych znaczników: <produkty-tytul/> - niektóre
przeglądarki źle współpracują z dowolnymi samozamkniętymi znacznikami.
Angular, cz. II
10/30
Definiowanie własnej dyrektywy III
Definicja dyrektywy będącej atrybutem znacznika
Dyrektywa <h3 produkt-tytul></h3> wymaga następującej definicji:
app.directive(’produktTytul’, function(){
return {
restrict: ’A’,
templateUrl: ’produkt-tytul.html’
};
});
restrict - określa typ dyrektywy. ’A’ od słowa ’Attribute’ czyli dyrektywa
będzie atrybutem elementu HTML.
Po załadowaniu kod może być następujący:
<h3 class="ng-binding" produkt-tytul="">Aparat fotograficzny
<em class="pull-right ng-binding">458,99&nbsp;zł</em>
</h3>
Angular, cz. II
11/30
Własne dyrektywy zawierające kontroler I
Fragment strony HTML korzystający z kontrolera przenosimy do osobnego
pliku HTML. Fragment związany z panelami produktów na stronie:
<div ng-controller="PanelController as panel">
...
</div>
Zamieniamy na:
<produkty-panel ng-controller="PanelController as panel">
...
</produkty-panel>
Tworzymy dyrektywę:
app.directive(’produktyPanel’, function(){
return {
restrict: ’E’,
templateUrl: ’produkty-panel.html’,
};
});
Przydało by się przenieść kontroler do utworzonej dyrektywy...
Angular, cz. II
12/30
Własne dyrektywy zawierające kontroler II
Obiekt definiujący dyrektywę zawiera dwie dodatkowe opcje konfiguracyjne:
controller - określa funkcjonalność kontrolera przypisanego do
dyrektywy.
Tutaj przenosimy funkcjonalność kontrolera, który chcemy związać z
definiowaną dyrektywą.
controllerAs - określa alias, jakim będziemy się podługiwać w
obszarze zdefiniowanej dyrektywy.
W naszym przypadku będzie to: controllerAs: ’panel’.
app.directive(’produktyPanel’, function(){
return {
...
controller: function() {
...
},
controllerAs: ’panel’,
};
});
Wygodnie jest mieć funkcjonalność razem ze zdefiniowaną dyrektywą.
Angular, cz. II
13/30
Własne dyrektywy zawierające kontroler III
Całość dyrektywy przedstawia się następująco:
app.directive(’produktyPanel’, function(){
return {
restrict: ’E’,
templateUrl: ’produkty-panel.html’,
controller: function() {
this.tab = 1;
this.setTab = function(sTab) {
this.tab = sTab;
};
this.isSelected = function(sTab) {
return this.tab === sTab;
};
},
controllerAs: ’panel’,
};
});
Angular, cz. II
14/30
Moduły
Kiedy nasz kod robi się za duży warto podzielić go na moduły.
Tworzymy nowy plik, np. produkty.js, w którym umieszczamy kod:
(function(){
var app = angular.module(’sklep-produkty’, [ ]);
app.directive(’produktTytul’, function(){ . . . });
app.directive(’produktyPanel’, function(){ . . . });
app.directive(’galeria’, function(){ . . . });
})();
angular.module(); - definicja nowego modułu.
’sklep-produkty’ to nazwa modułu. W nawiasach kwadratowych są
zależności.
Ponowne użycie zmiennej app (taka sama nazwa w głównym module
aplikacji) nie stwarza problemu - obie zmienne mają zasięg ograniczony
wewnątrz modułów.
Angular, cz. II
15/30
Moduły - zależności
W głównym module aplikacji dodajemy utworzony moduł:
(function(){
var app = angular.module(’sklep’, [’sklep-produkty’]);
app.controller(’StoreController’, function(){
...
});
. . .
})();
Dodatkowo należy dołączyć plik nowego modułu do strony:
<script type="text/javascript" src="produkty.js"></script>
Angular, cz. II
16/30
Usługi
Usługi pozwalają nam m.in. na pobranie danych z zewnętrznego źródła.
Lista produktów w naszych przykładach powinna być pobierana z jakiegoś
API, w naszym przypadku JSON.
Produkty wykorzystywane w przykładach dostępne poprzez stronę
http://www.json-generator.com/api/json/get/bINYWeJauW?indent=2
Zawartość:
[
{
"komentarze": [
{
"autor": "[email protected]",
"tresc": "Bardzo fajny aparat. Uwielbiam go!",
"ocena": 5
},
. . .
]
Angular, cz. II
17/30
Usługi w Angular
Angular posiada wiele wbudowanych usług.
Usługi pozwalają dodać do naszego kontrolera dodatkową
funkcjonalność.
Wszystkie usługi wbudowane w Angular zaczynają się od znaku $.
Usługi pozwalają na:
Pobranie danych w postaci JSON z usługi internetowej (web service)
przez usługę $http.
Zapis logów do konsoli JavaScript za pośrednictwem usługi $log.
Filtrowanie zawartości tablic za pomocą usługi $filter.
Angular, cz. II
18/30
Usługa $scope
Usługa $scope:
ma specjalne znaczenie, odróżnia się od innych usług,
służy do udostępniania danych i funkcji widokom,
udostępnianie odbywa się w kontrolerze.
Jeśli chcemy żeby widoki miały dostęp do całego modelu to można
przypisać do jakiejś właściwości obiektu $scope cały model, np.:
$scope.lista = model;
Dwa rodzaje dostępu do danych modelu w widoku:
obiekt $scope,
wykorzystanie aliasu kontrolera.
Angular, cz. II
19/30
Dane w widoku - wykorzystanie $scope
Wykorzystanie usługi $scope w kontrolerze
w funkcji kontrolera jest parametr $scope,
obiekt $scope udostępni dane i funkcje do widoku
app.controller(’HelloController’, function($scope) {
$scope.produkt = ciastko;
});
var ciastko = {
nazwa: ’Ciasteczka’,
cena: 2.95,
opis: ’Smaczne i zdrowe’
}
Wykorzystanie właściwości produkt obiektu $scope w widoku:
<div ng-controller="HelloController">
<h3>{{produkt.nazwa}}</h3>
<code>{{produkt.cena | currency}}</code>
<p>{{produkt.opis}}</p>
</div>
Angular, cz. II
20/30
Dane w widoku - wykorzystanie aliasu
Kontroler bez obiektu $scope
w funkcji kontrolera nie ma przekazanego żadnego parametru,
w dołączeniu kontrolera w widoku musi być użyty alias
app.controller(’HelloController’, function() {
this.produkt = ciastko;
});
var ciastko = {
nazwa: ’Ciasteczka’,
cena: 2.95,
opis: ’Smaczne i zdrowe’
}
Wykorzystanie danych modelu w widoku za pomocą aliasu hello:
<div ng-controller="HelloController as hello">
<h3>{{hello.produkt.nazwa}}</h3>
<code>{{hello.produkt.cena | currency}}</code>
<p>{{hello.produkt.opis}}</p>
</div>
Angular, cz. II
21/30
Usługa $http
Usługa $http pozwala nam wykonać asynchroniczne zapytanie do
serwera.
Można użyć $http jako funkcji z obiektem zawierającym opcje:
$http({ method: ’GET’, url: ’/produkty.json’ });
Można też użyć jednej z metod usługi $http:
$http.get(’/produkty.json’, { apiKey: ’myApiKey’ });
Obie metody zwracają objekt Promise. Na takim obiekcie można
wykonać funkcje zwrotne .success() albo .error().
Jeśli usługa $http pobiera JSON to wynik zostanie automatycznie
przekształcony do objektu czy tablicy JavaScript.
Angular, cz. II
22/30
Usługa $http
Kontroler musi poinformować Angular jakich usług potrzebuje.
W tym celu używamy takich dziwnych wyrażeń tablicowych
app.controller(’PrzykladowyKontroler’, [ ’$http’, function($http){
} ]);
’$http’ oznacza nazwę usługi; w tablicy najpierw określamy nazwy usług.
$http to usługa przekazywana jako argument do funkcji kontrolera; w ten
sposób można użyć $http wewnątrz kontrolera.
Taki sposób przekazywania usług potrzebnych kontrolerowi nazywa się
wstrzykowaniem zależności (ang. dependency injection).
Injector przekazuje usługi wymagane przez kontroler jako argumenty. Stąd wstrzykiwanie zależności, bo injector
wstrzykuje zależnośći (w tym przypadku usługi) do funkcji kontrolera jako argumenty.
Wyrażenie w przypadku dwóch usług:
app.controller(’JakisKontroler’, [ ’$http’, ’$log’, function($http, $log){
} ]);
Angular, cz. II
23/30
Usługa $http - przykład
Przykład wykorzystania usługi $http w kontrolerze z pobraniem listy
produktów przy wykorzystaniu funkcji zwrotniej success().
(function(){
var app = angular.module(’sklep’, [’sklep-produkty’]);
app.controller(’StoreController’, [ ’$http’, function($http){
this.produkty = ???
$http.get(’/produkty.json’).success(function(data){
??? = data;
});
}]);
})();
Lista produktów jest zwrócona w obiekcie data.
Dane należy przypisać do this.produkty ale nie możemy się odwołać do
tych danych wewnątrz funkcji zwrotnej. this wewnątrz funkcji zwrotnej
wskazuje na usługę $http. Więc?
Angular, cz. II
24/30
Usługa $http - przykład
Przykład wykorzystania usługi $http w kontrolerze z pobraniem listy
produktów przy wykorzystaniu funkcji zwrotniej success().
(function(){
var app = angular.module(’sklep’, [’sklep-produkty’]);
app.controller(’StoreController’, [ ’$http’, function($http){
var sklep = this;
$http.get(’/produkty.json’).success(function(data){
sklep.produkty = data;
});
}]);
})();
Lista produktów jest zwrócona w obiekcie data.
Dane należy przypisać do this.produkty ale nie możemy się odwołać do
tych danych wewnątrz funkcji zwrotnej. this wewnątrz funkcji zwrotnej
wskazuje na usługę $http. Więc? Użyjemy zmiennej pomocniczej.
Angular, cz. II
25/30
Usługa $http - przykład
Wykonanie zapytania asynchronicznego i zwrócenie wyniku może
zająć jakiś czas.
Strona nie będzie na to czekać i może się załadować bez listy
produktów.
Dobrym pomysłem będzie wstępne zainicjowanie zmiennej:
sklep.produkty = [ ];
Angular, cz. II
26/30
Usługa $http + $scope - przykład
Przykład wykorzystania usługi $http w kontrolerze z pobraniem listy osób z
API, wykorzystanie funkcji zwrotnych success() oraz error().
(function(){
var app = angular.module(’formularz’, [ ]);
app.controller(’FormularzController’, [’$scope’,’$http’,
function($scope,$http){
$http.get(’https://przyklad.com/students’)
.success(function(data){
$scope.users = data;
})
.error(function(){
alert("error");
});
}]);
})();
Angular, cz. II
27/30
Usługa $http.post - przykład
Przykład wykorzystania usługi $http w kontrolerze z pobraniem listy osób z
API, wykorzystanie funkcji zwrotnych success() oraz error().
(function(){
...
$http.post(
’https://przyklad.com/students’,
{ "name":"Jan", "surname":"Nowicki", "age": 19 })
.success(function(data){
alert("OK");
})
.error(function(){
alert("error");
});
}]);
...
})();
Angular, cz. II
28/30
Usługa $http - dodatkowa funkcjonalność
Poza metodą get() usługa $http zawiera jeszcze post(), put(),
delete(), ...
$http.post(’/sciezka/do/zasobow.json’, { param: ’value’ });
$http.delete(’/sciezka/do/zasobow.json’);
Można również używać dowolnych innych metod usługi $http
korzystając z obiektów z konfiguracją:
$http({ method: ’OPTIONS’, url: ’/sciezka/do/zasobow.json’ });
$http({ method: ’PATCH’, url: ’/sciezka/do/zasobow.json’ });
$http({ method: ’TRACE’, url: ’/sciezka/do/zasobow.json’ });
Angular, cz. II
29/30
Warto zobaczyć
https://egghead.io/ - Kursy video dla AngularJS, React, D3 i
innych kluczowych technologi internetowych.
https://thinkster.io/ - Nauka nowoczesnych technologii
internetowych, również zawiera filmy video
https://kapeli.com/dash - Dokumentacja offline do bardzo wielu
API technologi internetowych - warto pobrać!
Angular, cz. II
30/30