Angular, cz. I - Instytut Informatyki Teoretycznej i Stosowanej
Transkrypt
Angular, cz. I - Instytut Informatyki Teoretycznej i Stosowanej
Angular, cz. I Angular, cz. I 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/48 Plan prezentacji 1 Framework 2 Angular 1.5 Hello World Internacjonalizacja i lokalizacja Wyrażenia Filtry Moduły Kontroler Dyrektywy show, hide, repeat, src click, init, class, model Kontroler - prosta logika Formularze Dyrektywy submit, options Sprawdzanie poprawności - walidacja 3 Źródła Angular, cz. I 2/48 Framework I Framework (platforma programistyczna) - szkielet do budowy aplikacji. Definiuje strukturę aplikacji oraz ogólny mechanizm jej działania. Dostarcza zestaw komponentów i bibliotek. Tworzenie aplikacji polega na rozbudowie i dostosowaniu poszczególnych komponentów do wymagań określonego projektu. Framework to nie biblioteka oprogramowania. Framework to samodzielna kategoria oprogramowania. Angular, cz. I 3/48 Framework II Framework to samodzielna kategoria oprogramowania, świadczą o tym takie cechy jak: Odwrócenie sterowania - przepływ sterowania jest narzucony przez framework, nie przez użytkownika. Domyślne zachowanie - posiada domyślną konfigurację, która sama w sobie jest użyteczna i daje sensowny wynik, inaczej niż np. jQuery. Rozszerzalność - poszczególne komponenty są rozszerzalne przez programistę na potrzeby dodatkowej funkcjonalności. Zamknięta struktura wewnętrzna - framework można rozbudowywać ale nie przez modyfikację domyślnego kodu. Angular, cz. I 4/48 Framework III Framework składa się z zamrożonych i gorących punktów. Zimne punkty definiują ogólną architekturę konkretnego typu oprogramowania, tj. zestaw podstawowych komponentów i zależności między nimi. Ta architektura (zimne punkty), pozostają niezmienne dla danego frameworku. Ogólna architektura dla danego frameworku jest taka sama pośród różnych projektów w nim napisanych. Gorące punkty reprezentują te części projektu, które programista rozszerza. Gorące punktu są osadzone we frameworku a nie na odwrót. Klasy i komponenty użytkownika otrzymują syngały od frameworka, który zarządza wykonywaniem aplikacji. Widać tutaj różnicę w porównaniu do biblioteki oprogramowania. Angular, cz. I 5/48 Framework IV - wady i zalety Zalety: efektywność - programista pisze mniej kodu, bo już bardzo dużo jest przygotowane, poprawa jakości kodu - framework ma być elastyczny więc ma dobrze przemyślaną organizację wewnętrzną i logikę, niezawodność - jak coś jest dobrze przygotowane i przetestowane, a takie oczekiwania stawia się szkieletom aplikacji, to nie powinno być błędów czy większych problemów z działaniem. Wady: złożoność - nie łatwo się nauczyć frameworka, bo jest on przygotowany jako elastyczny i używa wielu zaawansowanych koncepcji, wydajność - jak budowa jest elastyczna to często kosztem szybkości działania. Angular, cz. I 6/48 AngularJS - wersja 1.5 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. I 7/48 Hello World - szablon HTML index.html <!DOCTYPE html> <html ng-app="hello"> <head> <script type="text/javascript" src="angular.min.js"></script> <script type="text/javascript" src="app.js"></script> </head> <body> <p>{{4+6}}</p> </body> </html> app.js var app = angular.module(’hello’, [ ]); Angular, cz. I 8/48 Hello World - opis ng-app - dyrektywa, która tworzy aplikację Angular kiedy strona jest wczytywana: <html lang="pl" ng-app="hello"> należy też dołączyć bibliotekę Angular: <script type="text/javascript" src="angular.min.js"></script> a także plik z utworzonym modułem: <script type="text/javascript" src="app.js"></script> w pliku app.js jest definicja modułu, który nic nie robi, ale dołączony pozwala traktować cały kod wewnątrz elementu, do którego jest dołączony jako aplikację Angular var app = angular.module(’hello’, [ ]); teraz w zakresie zancznika <html> można używać wyrażeń, np.: {{(3+5*4)/2}} - otrzymamy wartość 11.5 {{’Hello ’+" World"}} - Hello World Angular, cz. I 9/48 Internacjonalizacja i lokalizacja internationalization (i18n), localization (l10n): proces tworzenia produktu w taki sposób, żeby łatwo było dostosować go do potrzeb języka czy kultury, trzeba dostarczyć tłumaczenie słów, formatów danych, ... do lokalnych potrzeb. Angular wspiera i18n/l10n dla dat, liczb i walut. ID lokalizacyjne: id określające region geograficzny, polityczny czy kulturalny, najczęściej składa się z dwóch części: kod języka-kod kraju, przykłady: en-US, en-AU, pl-PL, ... ale też: en, pl, sk, ... Angular, cz. I 10/48 Internacjonalizacja II Pliki ze skryptami do lokalizacji: https://github.com/angular/angular.js/tree/master/src/ngLocale Dwa polskie (niczym się nie różnią): angular-locale pl.js angular-locale pl-pl.js dużo innych ... Dwa podejścia: dodanie lokalizacji na stałe do skryptu angular.js: cat angular.js angular-locale_pl-pl.js > angular_pl-pl.js dołączenie skryptu z lokalizacją do pliku html: <html ng-app> <head> ... <script src="angular.min.js"></script> <script src="angular-locale_pl-pl.js"></script> </head> </html> Angular, cz. I 11/48 Obsługa liczby mnogiej - ng-pluralize Język polski (kod: pl) Kategoria jeden (one) kilka (few) Przykład 1 2-4, 22-24, 32-34... wiele (many) 0, 5-21, 25-31, 35-41... inne (other) 1.2, 2.07, 5.94... Zasady n wynosi 1 n mod 10 w granicach 2..4 AND n mod 100 poza zakresem 12..14; n różne od 1 AND n mod 10 w zakresie 0..1 OR n mod 10 w zakresie 5..9 OR n mod 100 w zakresie 12..14 wszystkie inne liczby Dyrektywa ng-pluralize: wyświetla informacje zgodnie z odmianą liczebników w danym języku, należy określić mapowanie między kategoriami liczbeności a wyświetlanymi napisami, kategorie liczebności to konkretne liczby albo grupy liczb, posiada parametr offset, który określa na lepsze sprecyzowanie wyświetlanego tekstu. Angular, cz. I 12/48 Przykład ng-pluralize <label>Liczba kotów: <input type="text" ng-model="catCount" value="0" /></label><br/> <div ng-pluralize count="catCount" when="{’0’ : ’0 kotów, czyli brak :)’, ’one’ : ’1 kot’, ’few’ : ’*2,*3,*4 koty’, ’many’ : ’*5,*6,*7,*8,*9,*0,... kotów’, ’other’: ’{} kotów jest na dachu’}"> </div> <ng-pluralize count="catCount" when="{’0’ : ’0 kotów, czyli brak :)’, ’one’ : ’1 kot’, ’few’ : ’*2,*3,*4 koty’, ’many’ : ’*5,*6,*7,*8,*9,*0,... kotów’, ’other’: ’{} kotów jest na dachu’}"> </ng-pluralize><br><br> Angular, cz. I 13/48 Przykład ng-pluralize <label>Osoba 1: <input type="text" ng-model="os1" value="" /></label><br/> <label>Osoba 2: <input type="text" ng-model="os2" value="" /></label><br/> <label>Liczba osób: <input type="text" ng-model="personCount" value="1" /></label><br/> Bez przesunięcia (offset): <ng-pluralize count="personCount" when="{’0’ : ’Nikt nie ogląda strony’, ’one’ : ’1 osoba (one) ogląda stronę’, ’few’ : ’{} (few) osoby oglądają stronę’, ’many’ : ’{} (many) osób ogląda stronę’, ’other’: ’Inna liczba (other) osób ({}) ogląda stronę’}"> </ng-pluralize><br> Z przesunięciem równym 2: <ng-pluralize count="personCount" offset=2 when="{’0’ : ’Nikt nie ogląda strony’, ’1’ : ’{{os1}} ogląda stronę’, ’2’ : ’{{os1}} i {{os2}} oglądają stronę’, ’one’ : ’{{os1}} i {{os2}} i jeszcze jedna osoba oglądają stronę’, ’few’ : ’{{os1}} i {{os2}} i jeszcze {} inne osoby oglądają stronę’, ’many’: ’{{os1}} i {{os2}} i jeszcze {} innych osób ogląda stronę’ }"> </ng-pluralize> Angular, cz. I 14/48 Wyrażenia Wyrażenia pozwalają na wyświetlanie różnych danych na stronie. {{4+6}} - operacje numeryczne, tutaj dodawanie, {{"Hello" + " World"}} - Hello World - operacje na napisach, {{3.1*12|currency}} - $37.20 - operacja numeryczna z filtrem walutowym (internacjonalizacja), {{sklep.produkt.opis}} - ’Treść opisu...’ - wyświetla zawartość pola opis właściwości produkt kontrolera sklep, {{ zm[index]>2 ? 100 : 0.12 }} - z wyjątkiem operatora ?: nie można kontrolować przepływu sterowania, {{::nazwa}} vs {{nazwa}} - :: przed nazwą zmiennej - jednokrotne wiązanie, po ustalonej wartości takie wyrażenia nie zmienią już swojej wartości - dla zwiększenia wydajności wtrony. Angular, cz. I 15/48 Filtry Filtry: wykorzystujemy za pośrednictwem symbolu | (jak potoki w linux’ie). Angular ma kilka filtrów. W widoku wykorzystujemy je w następująco: // Proste zastosowanie {{ wyrażenie | filtr }} // Przetwarzanie potokowe {{ wyrażenie | filtr1 | filtr2 | ... }} // Wykorzystanie argumentów (opcji) {{ wyrażenie | filtr:argument1:argument2:... }} Można ich używać: w szablonie widoku, kontrolerach, usługach czy dyrektywach. Istnieje możliwość definiowania własnych filtrów ($filterProvider). Angular, cz. I 16/48 Lista filtrów I currency - filtr walutowy z internacjonalizacją; wyświetalnie walut, filtr automatycznie dodaje miejsca po przecinku i oznaczenie waluty {{ wyrażenieWalutowe | currency : symbolWaluty : miejscaPoPrzec}} {{7 | currency}} - 7,00 zł {{13.9501 | currency:’PLN’:1}} - 14,0 PLN date - filtr wyświetlania daty (obiekt daty, timestamp albo string) {{ wyrażenieDatyCzasu | date : format : strefaCzasowa}} {{’1427110041593’ | date:’MM/dd/yyyy @ h:mma’}} - 03/23/2015 @ 12:27PM {{sklep.data | date:"MM-dd-yy ’godz.’ h:mm:ss"}} - 03-23-15 godz. 1:09:29 filter - wybiera podzbiór z tablicy i zwraca go jako nową tablicę {{ wyrażenieTablica | filter : predykat : precyzjeDokładność}} <div ng-init="friends = [{name:’John’, phone:’555-1276’}, {name:’Mary’, phone:’800-BIG-MARY’}, {name:’Mike’, phone:’555-4321’}, {name:’Adam’, phone:’555-5678’}, {name:’Julie’, phone:’555-8765’}, {name:’Juliette’, phone:’555-5678’}]"> </div> {{friends|filter:12:strict}} - [{"name":"John","phone":"555-1276"}] Angular, cz. I 17/48 Lista filtrów II json - konwertuje obiekty JavaScript do formatu json {{ wyrażenieObjektJS | json : liczbaSpacji}} <pre id="custom-spacing">{{ {’name’:’value’, age:12.4} | json:4 }}</pre> { "name": "value", "age": 12.4 } limitTo - ograniczenie wyświetlanego napisu {{ wyrażenieWejściowe | limitTo : długośćNaWyjściu : początek}} {{’Slonce jest dzisiaj wysoko.’ | limitTo:4}} - Slon <br> {{’Slonce jest dzisiaj wysoko.’ | limitTo:4:7}} - jest <br> {{’Slonce jest dzisiaj wysoko.’ | limitTo:-4}} - oko.<br> {{’Slonce jest dzisiaj wysoko.’ | limitTo:-4:6}} - once<br> {{’Slonce jest dzisiaj wysoko.’ | limitTo:-4:-6}} - aj w<br> <div ng-repeat="rzecz in sklep.produkty | limitTo:3"> - tylko 3 elementy lowercase - zmiana na małe litery {{’Skrót JavaScript ...’ | lowercase}} - skrót javascript ... Angular, cz. I 18/48 Lista filtrów III number - formatuje liczby jako napisy z liczbą miejsc po przecinku {{ wyrażenieLiczbowe | number : miejscaPoPrzecinku}} <span>{{ 123.456789 | number }}</span> - 123,457 <span>{{ 123.456789 | number:0}}</span> - 123 <span>{{-123.456789 | number:4}}</span> - -123,4568 orderBy - wyświetlanie według określonego porządku {{ obiektDoPosortowania | orderBy : predykat : odwóćKolejność}} <!-<div <!-<div <div rosnąco według ceny --> ng-repeat="rzecz in sklep.produkty | orderBy:’cena’"> malejąco według nazwy --> ng-repeat="rzecz in sklep.produkty | orderBy:’-nazwa’"> ng-repeat="rzecz in sklep.produkty | orderBy:’nazwa’:true"> uppercase - zmiana na duże litery {{’Ala ma kota’ | uppercase}} - ALA MA KOTA Angular, cz. I 19/48 Wywoływanie filtrów w JavaScript $filter(’currency’)(amount, symbol, fractionSize) $filter(’date’)(date, format, timezone) $filter(’filter’)(array, expression, comparator) $filter(’json’)(object, spacing) $filter(’limitTo’)(input, limit, begin) $filter(’lowercase’)() $filter(’number’)(number, fractionSize) $filter(’orderBy’)(array, expression, reverse) $filter(’uppercase’)() Angular, cz. I 20/48 Tworzenie własnych filtrów I Tworzenie własnego filtru: urzywamy słowa kluczowego filter i dwóch parametrów: nazwa filtru, funkcja anonimowa bez parametrów zwracająca funkcję filtrującą, tworzymy filtr jako składową wybranego modułu, moduł może zawierać tylko sam filtr - dołączany w miarę potrzeb. angular.module(’mojeFiltry’, []).filter(’mojNowyFiltr’, function() { return function(input) { return input ? ’\u2713’ : ’\u2718’; }; }); angular.module(’hello’, [...,’mojeFiltry’]); <p>{{ hello.zmienna | mojNowyFiltr }}</p> Angular, cz. I 21/48 Tworzenie własnych filtrów II app.js var app = angular.module(’hello’, [ ]); app.filter(’duzeMale’, function(){ var duzeMaleFilter = function(input) { var napis = input.split(’’); for (var i=0; i<napis.length; i++) { if (i%2===0) { napis[i] = napis[i].toUpperCase(); } else { napis[i] = napis[i].toLowerCase(); }; }; return napis.join(’’); }; return duzeMaleFilter; }); index.html <h3>{{ "Nagłówek pierwszy testujący nowy filtr" | duzeMale }}</h3> <h3>{{ "Nagłówek drugi testujący nowy filtr" | wyrazZDuzej }}</h3> Angular, cz. I 22/48 Moduły Moduły są przestrzenią, w którym nasza aplikacja się znajduje. Moduł to jakiś nasz zakapsułkowany fragment funkcjonalności. Moduły zawierają właściwości, którym przypisujemy funkcje albo dane, np. this.product = gem; W modułach podajemy zależności jakie są w naszej aplikacji, np. moduł a może zależeć od modułów b i c. app.js var app = angular.module(’hello’, [ ]); angular - oznacza bibliotekę AngularJS, z której korzystamy hello - nazwa nowo tworzonego modułu [ ] - tutaj określamy zależności, nie można pominąć tego argumentu, nawet jeśli moduł nie jest zależny od innych Angular, cz. I 23/48 Dyrektywy - ng-app Dyrektywy są atrybutami znaczników HTML, które włączają jakiś przypisane im działanie JavaScript. Dyrektywa ng-app: podłącza moduł aplikacji do strony, uruchamia moduł kiedy strona jest wczytywana, moduł jest w pliku JS dołączonym do strony (app.js). <!DOCTYPE html> <html ng-app="hello"> <head> <script type="text/javascript" src="angular.min.js"></script> <script type="text/javascript" src="app.js"></script> </head> <body> ... </body> </html> Angular, cz. I 24/48 Kontroler W kontrolerze definiujemy zachowanie aplikacji poprzez definiowanie funkcji i zmiennych. Kontroler pozwala nam na pracę z danymi, które chcemy wyświetlać na stronie. Kilka różnych kontrolerów może być zdefiniowanych w jednym pliku *.js. Każdy kontroler powinien odpowiadać za jakąś logiczną całość - nie może być jeden kontroler do wszystkiego. Do połączenia kontrolera ze stroną HTML wykorzystujemy dyrektywę ng-controller, np. ng-controller="PanelController as panel" Sekcje inicjalizacji zmiennych i konfiguracji umieszcza się w kontrolerze. Angular, cz. I 25/48 IIFE IIFE - ”Immediately Invoked Function Expression” samowywołujące się funkcje anonimowe == wyrażenie funkcyjne natychmiastowo wywoływane, wzorzec projektowy języka JavaScript, pozwala tworzyć lokalny zasięg używając zasięgu funkcji, nie zaśmiecamy przestrzeni globalnej, zmienne znane tylko wewnątrz funkcji. (function() { // raz wywoływany kod we własnej przestrzeni })(); (function(a, b) { // a == ’hello’ // b == ’world’ })(’hello’, ’world’); Angular, cz. I 26/48 Dyrektywy - ng-controller ng-controller - pozwala dołączyć kontroler do naszego szablonu HTML (do jakiegoś znacznika, do fagmentu drzewa DOM) z jakimś aliasem, którego będziemy używać. ng-controller dołącza funkcje kontrolera do strony. Podajemy nazweKontrolera, słowo kluczowe as oraz alias, którego będziemy używać. Zasięg kontrolera jest tylko wewnątrz takiego znacznika, do którego został przypisany. <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. I 27/48 Kontroler - przykład Kontroler jest dodawany do naszej aplikacji: app.controller(...); Cały moduł wewnątrz autoamtycznie wywoływanej funkcji anonimowej. Tworząc kontroler podajemy jego nazwę, tutaj HelloController i jego zawartość jako wnętrze funkcji anonimowej Poniżej w kontrolerze utworzono zmienną produkt, której przypisano obiekt ciastko - jego zawartość będzie wyświetlana na stronie. (function(){ var app = angular.module(’hello’, [ ]); app.controller(’HelloController’, function(){ this.produkt = ciastko; }); var ciastko = { nazwa: ’Ciasteczka’, cena: 2.95, opis: ’Smaczne i zdrowe’ } })(); Angular, cz. I 28/48 Kontroler - przykład Dyrektywa ng-controller pozwala na wykorzystanie zmiennych kontrolera na stronie. Korzystamy tutaj z aliasu hello, który jest przypisany nazwie kontrolera, tutaj HelloController. Wyrażenia pozwalają wyświetlić zawartość obiektu produkt. <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. I 29/48 Dyrektywy - ng-show, ng-hide ng-show - pokazuje element HTML (gałąź drzewa DOM) kiedy wartość wyrażenia jest prawdziwa, np.: ng-show="sklep.produkt.dostepny" Jeśli pola dostepny w ogóle brak, to dyrektywa ng-show uzna brak pola jako false i nie pokaze danego elementu. ng-hide - ukrywa element kiedy wartość wyrażenia jest prawdziwa. ng-show/ng-hide - pokazuje/ukrywa jakiś fragment drzewa DOM. Można użyć na przykład do ukrycia galerii kiedy tablica images będzie pusta: <div ng-show="product.images.length"> ... </div> W dyrektywach wyrażenia można łączyć warunkami logicznymi z mniejszych wyrażeń, np.: ng-show=" komentarz.ocena>0 || komentarz.tresc.length>0 || komentarz.autor.length>0" Angular, cz. I 30/48 Dyrektywy - ng-repeat ng-repeat - dyrektywa tworzy instancje przypisanego jej szablonu (zawartość znacznika) tyle razy, ile posiada elementów w kolekcji, którą iteruje. Składnia: ng-repeat="nazwaZmiennej in kolekcja" nazwaZmiennej przechowującej kolejne elementy kolekcji, słowo kluczowe in, kolekcja - tablica, po której iterujemy. Każda instancja ma swój własny zasięg, w którym zmienna wykorzystana w pętli ma wartość odpwiedniego elementu kolekcji. Można wykorzystwać specjalne właściwości, np. $index która zwraca numer elementu w kolekcji (0..length-1) Przykłady: ng-repeat="produkt in sklep.produkty" <p ng-repeat="aa in [3,4,5,6,7,8]"> {{aa}} - {{$index}} </p> <p ng-repeat="(aa, bb) in {’a’:123, ’b’:234, ’c’:456}"> {{aa}} - {{bb}} - {{$index}} </p> Angular, cz. I 31/48 Dyrektywy - ng-src ng-src - zastępuje zwykły zapis w <img src="..." /> Wykorzystujemy wyrażenia np. {{produkt.obrazy[0].caly}} Wczytywanie obrazów odbywa się zanim zadziała analiza wyrażeń w Angular. Trzeba użyć dyrektywy ng-src. Przykład: <img src="{{rzecz.obrazy[0].caly}}" /> <img ng-src="{{rzecz.obrazy[0].ikona}}" /> Angular, cz. I 32/48 Dyrektywy - ng-click ng-click - ta dyrektywa przyjmuje wyrażenie, które musi zostać wykonane, obliczone. Można tutaj zmiennej przypiswyać różne wartości. <h1>Karty w Twitter Bootstrap</h1> <section> <ul class="nav nav-pills"> <li> <a href ng-click="tab = 1">Opis</a></li> <li> <a href ng-click="tab = 2">Specyfikacja</a></li> <li> <a href ng-click="tab = 3">Przegląd</a></li> </ul> <p>Kliknięto kartę nr. {{tab}}</p> </section> Takie wyrażenia definiują dwukierunkowe wiązania danych: 1 kliknięcie powoduje zmianę wartości zmiennej tab, 2 wartości wyrażeń są ponownie wyznaczane kiedy właściwość ze zmienną się zmieni (np. po kliknięciu). Tak więc wyrażenie ”śledzi” kiedy zmieni się wartość tab i wtedy, kiedy się zmieni, to zmiana jest od razu aktualizowana na stornie. Angular, cz. I 33/48 Dyrektywy - ng-init ng-init - pozwala na określenie wartości wyrażenia w danym zasięgu możemy zmiennej przypisać wartość. Można wykorzystać do określenia wartości zmiennej przy przeładowaniu strony. Dobrze nadaje się prototypowania, eksperymentowania przy towrzeniu kodu. Po średniku (;) można inicjować więcej niż jedną zmienną. W poniższym przykładzie przypisujemy zmiennej tab wartość 1 oraz zmiennej rzecz obiekt odpowiadający pierwszemu produktowi. <h1>Trzy panele z informacjami</h1> <section ng-init="tab = 1; rzecz = sklep.produkty[0]"> <div class="panel" ng-show="tab === 1"> <h4>Opis</h4> <p>{{rzecz.opis}}</p> </div> <div class="panel" ng-show="tab === 2"> <h4>Specyfikacja</h4> <p>Na razie brak...</p> </div> <div class="panel" ng-show="tab === 3"> <h4>Przegląd</h4> <p>Na razie nie ma...</p> </div> </section> Angular, cz. I 34/48 Dyrektywy - ng-class ng-class - pozwala na dodawanie klas do danego elementu czy całej gałęzi DOM. Składnia: ng-class="{ klasa:wyrażenie }" klasa jest nazwą klasy jaką chcemy dodać, do znacznika. wyrażenie zwraca wartość logiczną, która musi być prawdziwa żeby tę klasę dodać do danego znacznika. <h1>Karty w Twitter Bootstrap</h1> <section> <ul class="nav nav-pills"> <li ng-class="{ active:tab === 1 }"> <a href ng-click="tab = 1">Opis</a> </li> <li ng-class="{ active:tab === 2 }"> <a href ng-click="tab = 2">Specyfikacja</a> </li> ... </ul> </section> Angular, cz. I 35/48 Dyrektywy - ng-model ng-model wiąże wartość elementu formularza z właściwością (zmienną). Pozwala związać zmienne z konkretnym elementem formularza Składnia: <input ng-model="zmienna" type="text" /> Widać tutaj dwukierunkowe wiązanie danych: zmiana w polu formularza automatycznie aktualizuje wartości zmiennych na stronie. <form name="komentarzeFormularz"> <p>Podgląd zmian: {{komentarz.linia}}</p> <input ng-model="komentarz.linia" type="text" /> </form> Angular, cz. I 36/48 Dyrektywy - ng-model ng-model można wykorzystywać do różnych elementów formularza: select (lista rozwijana), zmienna ma wartość wybranej pozycji z listy textarea (obszar tekstowy), zmienna ma wartość obszaru tekstowego checkbox (pole wyboru), zmienna związana ma wartość true lub false text (pole tekstowe), zmienna ma wartość pola tekstowego email (pole tekstowe do adresu email), zmienna ma wartość wpisanego maila radio buttons (pole opcji), zmienna ma wartość wybranej opcji date time ... Angular, cz. I 37/48 Dyrektywy - ng-model <form name="komentarzeFormularz"> <blockquote> <b>Ocena: {{komentarz.ocena}}</b> {{komentarz.tresc}} <cite>- {{komentarz.autor}}</cite> <p>{{komentarz.linia}}</p> <p>{{komentarz.daneOsobowe}}</p> <p>{{komentarz.wybor}}</p> </blockquote> <select ng-model="komentarz.ocena"> <option value="0">Oceń produkt</option> <option value="1">1 gwiazdka</option> <option value="2">2 gwiazdki</option> ... </select> <textarea ng-model="komentarz.tresc"></textarea> <input ng-model="komentarz.autor" type="email" /> <input ng-model="komentarz.linia" type="text" /> <input ng-model="komentarz.daneOsobowe" type="checkbox" /> Zgadzam się ... <input ng-model="komentarz.wybor" type="radio" value="biały" /> <input ng-model="komentarz.wybor" type="radio" value="czerwony" /> <input type="submit" value="Oceń" /> </form> Angular, cz. I 38/48 Dyrektywy - ng-class, ng-model Przypisuje do paragrafu wpisane do pola tekstowego klasy: <style type="text/css"> .strike { text-decoration: line-through; } .bold { font-weight: bold; } .red { color: red; } </style> <p ng-class="style">Using String Syntax</p> <input type="text" ng-model="style" placeholder="Type: bold strike red"> Poniższy kod wyświetla napis „Napis dowolnym kolorem” w kolorze podanym w polu tekstowym: <p style="color: {{style}}">Napis dowolnym kolorem</p> <input type="text" ng-model="style" placeholder="Wpisz kolor: red,blue..."> Angular, cz. I 39/48 Kontroler - logika wewnątrz Kontroler zawiera: inicjalizację zmiennych - np. tab, funkcje operujące na tych zmiennych - tutaj selectTab(num) oraz isSelected() app.controller(’PanelController’, function(){ this.tab = 1; this.selectTab = function(setTab) { this.tab = setTab; }; this.isSelected = function(checkTab) { return this.tab === checkTab; }; }); Angular, cz. I 40/48 Kontroler - logika wewnątrz Wykorzystanie logiki kontrolera w kartach, zakładkach: <section ng-controller="PanelController as panel""> <ul class="nav nav-pills"> <li ng-class="{ active: panel.isSelected(1) }"> <a href ng-click="panel.selectTab(1)">Opis</a> </li> <li ng-class="{ active: panel.isSelected(2) }"> <a href ng-click="panel.selectTab(2)">Specyfikacja</a> </li> ... </ul> </section> Logika kontrolera w pokazywaniu elementów: <section ng-controller="PanelController as panel"> <div class="panel" ng-show="panel.isSelected(1)"> <h4>Opis</h4> <p>{{sklep.produkty[0].opis}}</p> </div> <div class="panel" ng-show="panel.isSelected(2)"> <h4>Specyfikacja</h4> <p>{{sklep.produkty[0].specyfikacja}}</p> </div> ... </section> Angular, cz. I 41/48 Dyrektywy - ng-submit ng-submit - pozwala wywołać funkcję kiedy formularz jest zatwierdzany. <form name="komentarzeFormularz" ng-controller="ReviewController as komentarzCtrl" ng-submit="komentarzCtrl.dodajKomentarz(rzecz)"> ... <input type="submit" value="Oceń" /> </form> Angular, cz. I 42/48 Dyrektywy - ng-options ng-options - ten atrybut może być wykorzystany do dynamicznego generowania listy znaczników <option> elementu <select> używając tablicy obiektów uzyskanej z wykonania wyrażenia zawartego w ng-options. Składnia: ng-options="label for values in array" gdzie: label to nazwy etykiet, values to wartości przyporządkowane wybranym etykietom, array to tablica, względem której są budowane pola wyboru. Przykład: ng-options="stars+’ stars’ for stars in [5,4,3,2,1]" <select ng-model="komentarzCtrl.komentarz.ocena" ng-options="ocena+’ pkt.’ for ocena in [5,4,3,2,1]" required> <option value="">Oceń produkt</option> </select> W powyższym przykładzie wartości wybierane będą: 5,4,3,2,1 ale etykiety do nich przypisane będą: ’5 pkt.’, ’4 pkt.’, ’3 pkt.’,... Angular, cz. I 43/48 Walidacja - właściwości wbudowane, atrybuty $valid - wbudowana właściwość, która automatycznie waliduje każdy formularz, wymaga przypisanej do formularza nazwy. Znak $ oznacza odwołanie się do właściwości, w tym przypadku formularza, valid to właściwość wbudowana w Angular. Właściwość ta zwraca true, false zależnie, czy formularz się waliduje czy nie. Atrybut novalidate oznacza wyłączenie domyślnej walidacji HTML przeprowadzanej przez niektóre przeglądarki. Atrybut required oznacza te pola formularza, które są wymagane. <form name="komentarzeFormularz" ng-controller="ReviewController as komentarzCtrl" ng-submit="komentarzCtrl.dodajKomentarz(rzecz)" novalidate> ... <textarea ng-model="komentarzCtrl.komentarz.tresc" placeholder="Napisz którtki opis produktu..." required> </textarea> ... <div> komentarzeFormularz jest {{komentarzeFormularz.$valid}}</div> </form> Angular, cz. I 44/48 Walidacja - blokada wysłania formularza Wykorzystując właściwość $valid formularza należy zabezpieczyć się przed możliwością jego wysłania. Wystarczy dodać sprawczenie poprawności formularza w dyrektywie ng-submit: ng-submit="komentarzeFormularz.$valid && ..." <form name="komentarzeFormularz" ng-controller="ReviewController as komentarzCtrl" ng-submit="komentarzeFormularz.$valid && komentarzCtrl.dodajKomentarz(rzecz)" novalidate> ... <textarea ng-model="komentarzCtrl.komentarz.tresc" placeholder="Napisz którtki opis produktu..." required> </textarea> ... <div> komentarzeFormularz jest {{komentarzeFormularz.$valid}}</div> </form> Angular, cz. I 45/48 Walidacja - klasy związane z wprowadzaniem danych Angular podczas wprowadzania danych do formularza sam dodaje określone klasy do pól formularza. Klasy warte wykorzystania: ng-pristine - występuje jeśli wartość pola formularza nie uległa jeszcze zmianie, pole nie zostało jeszcze ”dotknięte”. ng-invalid - informuje, że wybrane pole, np. email, nie jest poprawne. ng-dirty - jeśli zaczniemy coś wpisywać do pola to ng-pristine zmieni się na ng-dirty - do pola są wprowadzane dane. ng-valid - jeśli dane są prawidłowe, np. prawidłowo wprowadzony adres email, to element będzie oznaczony klasą ng-valid. Przykład wykorzystania, plik style.css: .ng-invalid.ng-dirty { border-color: red; } .ng-valid.ng-dirty { border-color: green; } Angular, cz. I 46/48 Walidacja wbudowana w Angular Angular ma wbudowaną walidację najpopularnieszych typów danych wejściowych: adresów email, <input type="email" name="email"> adresów URL, <input type="url" name="homepage"> liczb, <input type="number" name="rozmiar">, dla liczb można sprecyzować wartość minimalną i maksymalną: min=1 max=23 pól tekstowych, <input type="text">, dat, <input type="date"> Walidacja w Angular: ważna ze względu na wygodę użytkownika - natychmiastowa weryfikacja poprawności danych, możliwość zablokowania wysłania formularza przy niepoprawnych danych, nie zapewnia bezpieczeństwa - zawsze wymagana jest również walidacja po stronie serwera. Angular, cz. I 47/48 Źródła W wykładzie wykorzystano informacje dostępne w internecie: https://angularjs.org/ https://docs.angularjs.org/api https://docs.angularjs.org/tutorial https://docs.angularjs.org/guide http://angular.codeschool.com/ Angular, cz. I 48/48