380 likes | 705 Views
Mateusz Uherek. Agenda. AngularJS REST-owe API w aplikacji Seam Komunikacja AngularJS z serwerem RESTEasy (wbudowanym w serwer JBoss ) Przykłady aplikacji wykorzystujących omówione technologie. ZACZYNAMY…. 3..2..1. AngularJS. MVC. Data- Binding. Directive. View. jqLite. Scope.
E N D
Agenda • AngularJS • REST-owe API w aplikacji Seam • Komunikacja AngularJS z serwerem RESTEasy (wbudowanym w serwer JBoss) • Przykłady aplikacji wykorzystujących omówione technologie
ZACZYNAMY… 3..2..1..
AngularJS MVC Data-Binding Directive View jqLite Scope Service Local Storage Factory Filter BUUUM! Module DependencyInjection Controller Routing Validation JavaScript SPA JSON
Co to ten AngularJS ? AngularJS jest w 100% javascript-owym framework-iem (SPA – Single PageAppliction) działającym po stronie klienckiej stworzonym przez Google, który kompatybilny jest z przeglądarkami desktop-owymi oraz mobilnymi. Z racji swojej wielkości często mylnie nazywany biblioteką. Umożliwia wdrożenie wzorca MVC (Model-View-Controller). Jedną z rzeczy, którą od razu wyróżnia jest to, że posiada własny kompilator HTML, przez możemy nauczyć go (html-a) nowych sztuczek.
Pobieramy Angularjs ze strony domowej http://angularjs.org Pobieramy plik js w najnowszej wersji tutaj! Po pobraniu +1 do magii Angulara
Zaczynamy… Plik html $scope to element łączący (klej) między widokiem a kontrolerem Kod js mający dostęp do $scope i zarządzający nim
Dyrektywy (Directive) Uczą HTML nowych trików NASZE WŁASNE!!! +10 do magii Angulara ng-app ng-show ng-model ng-bind
Połączmy to co wiemy w całość A teraz to co misie lubią najbardziej.. Miodziokodzik!
Magia angulara.. <html> <head> <scriptsrc="../angular-1.2.0.min.js"></script> <script> functionPierwszyKontroler($scope){ $scope.powitanie = 'Hello AngularJS'; } </script> </head> <body ng-app> <div ng-controller="PierwszyKontroler"> <p>To nasza pierwsza przygoda z AngularJS! </p> <p>Przywitajmy się:</p> <p>{{powitanie}}</p> </div> </body> </html> Umieszczamy skrypt angulara na stronie Definiujemy kontroler o nazwie PierwszyKontroler Umieszczamy dyrektywę ng-app informującą angulara o miejscu rozpoczęcia jego pracy Wykonanie polecenia zawartego w nawiasach angulara
Co tu się wydarzyło? • Angular automatycznie inicjuje się po zdarzeniu DOMContentLoaded lub . Od tego momentu angular szuka dyrektywy ng-app, która oznacza root aplikacji. Jeżeli angular ją znajdzie: • Ładuje moduł związany z dyrektywą • Tworzy wstrzykiwacz aplikacji („injectorapplication”) • Kompiluje DOM traktująć dyrektywy ng-app jako korzeń kompilacji. To pozwala, aby tylko część DOM traktować jako aplikację angulara.
WSTRzykiwanie zależności (DEPENDENCY INJECTION) functionPierwszyKontroler($scope){ $scope.powitanie = 'Hello AngularJS'; } Wstrzykiwanie zależności wykonujemy poprzez dodanie jej jako parametr funkcji kontrolera. Zależności rozpoznawane są po nazwie! Uwaga: W przypadku późniejszej minimalizacji plików i zmiany nazw parametrów wstrzyknięcia nie zadziałają w powyższej formie. Musimy zdefiniować dla angularowegoinjectora nazwy wstrzykiwanych zależności. functionPierwszyKontroler($scope){ $scope.powitanie = 'Hello AngularJS'; } PierwszyKontroler['$inject'] = ['$scope’]; Jest jeszcze druga możliwość – o niej później.
Data binding Twoway data binding - wszelkie zmiany w widoku są natychmiast odzwierciedlane w modelu(kontrolerze), a wszelkie zmiany w modelu(kontrolerze) są propagowane do widoku. To sprawia, że widok jest graficzną projekcją modelu(danych w kontrolerze).
<html> <head> <scriptsrc="../angular-1.2.0.min.js"></script> <script> functionDataBindingKontroler($scope){ $scope.imie; } </script> </head> <body ng-app> <div ng-controller="DataBindingKontroler"> <p>Data-binding </p> <p></p> <inputng-model="imie"></input> <p>Pierwszy sposób:</p> <spanng-bind="imie"></span> <p>Drugi sposób:</p> {{imie}} </div> </body> </html>
Moduł Tworzymy modulangulara. Jego nazwę umieszczamy w dyrektywie ng-app. varapp = angular.module('Routing',[]); app.config(function($routeProvider){ $routeProvider.when('/part1', {templateUrl:'./partial1.html',controller:'partial1Controller'}) .when('/part2/:id', {templateUrl:'./partial2.html',controller:'partial2Controller'}) .when('/part3', {templateUrl:'./partial3.html',controller:'partial3Controller'}) .otherwise({redirectTo:'/part1'}); }); Konfigurujemy nasz moduł przy pomocy routeProvider-a, który umożliwia nam tworzenie podstron w naszej aplikacji. Angular JS posiada funkcjonalność parsowania adresu podanego w przeglądarce i na podstawie niego wyświetla odpowiednią treść.
ROUTING …/nazwaNaszejAplikacji#/part1 …/nazwaNaszejAplikacji#/part2/123 …/nazwaNaszejAplikacji#/part3
HTML na dopalaczach – dyrektywy • ng-app • ng-show • ng-if • ng-repeat • ng-view • ng-model • …
Własne dyrektywy Tworzenie własnej dyrektywy polega na zdefiniowaniu obiektu dyrektywy i przekazaniu jej modułowi aplikacji: varmyModule = angular.module(...); myModule.directive('directiveName', function(injectables) { vardirectiveDefinitionObject = {…} }; return directiveDefinitionObject; });
Obiekt dyrektywy - parametry restrict – definiuje typ dyrektywy E – element (tak jak np. span) A – atrybut (tak jak np. class) C – klasa (nazwa klasy) M – komentarz priority – ustala priorytet dyrektywy w przypadku kilku dyrektyw przy jednym elemencie terminal – jeżeli ustawiony na true to obecny priorytet dyrektywy będzie ostatnim jaki zostanie wykonany(dyrektywy z mniejszym priorytetem nie zostaną uruchomione) template – zamienia obecny element na zdefiniowany w tym parametrze kod html. Wszystkie atrybuty i klasy zostają skopiowane do nowego elementu. templateUrl – to samo co template tylko zawartość html jest pobierana z podanego adresu. replace – jeżeli ustawiony na true to template labo templateUrl nadpisuje, a nie dopisuje zawartość.
Obiekt dyrektywy – parametry cd. scope – parametr ten opisuje w jaki sposób dyrektywa będzie defniowałascope: false – nie tworzy nowego scope tylko dzieli scope z rodzicem true – tworzy nowy scope „dziedzicząc” po rodzicu. Tworzony z prototypu rodzica. {} – definiuje odizolowany scope, do którego możemy przekazywać dane za pomocą atrybutów elementu 3 rodzaje tych parametrów: @ - wartość przekazana jako string = - łączy (twowaybinding) zmienne w odizolowanym scope-ie i rodzicem & - łączy metodę z rodzica, którą odizolowany scope może wykonać controller – tworzymy kontroler dla dyrektywy. Metody i właściwości mogą być dostępne przez wstrzyknięcie do innej dyrektywy za pomocą parametru reqiure require – umożliwia przekazaniu kontrolera zdefiniowanej w parametrze dyrektywy. Nazwe dyrektywy możemy poprzedzić ? – nie wywoluje błędu, umożliwia opcjonalne wstrzyknięcie albo ^ - szuka kontrolera w rodzicach elementu
Obiekt dyrektywy – parametry cd. compile – funkcja umożliwiająca manipulacje DOM. Wykonywana tylko raz przy kompilacji np. compilefunction(tElement, tAttrs) { tElement.append('Added during compilation phase!'); } link – funkcja łącząca DOM ze scope(twowaybinding). Wykonywana za każdym razem przy zmianie modelu. np. link: function(scope, element, attrs) { if (element.hasClass('btn')) { element.addClass('btn-primary'); } } Czas najwyższy na przykłady..
Pytania i ZADANIA • Napisać filtr do odwracania tekstu • Napisać dyrektywę podmieniającą element <my-widget> na tekst Hello ANGULAR • Napisać dyrektywę podmieniającą element z atrybutem my-widgetna tekst ustawiony jako wartość tego atrybutu • Napisać Dyrektywę powielającą zawartość elementu nrepeats tyle razy ile wsKaZuje atrybut tego elementu
Seam + RESTEASY – jak to zrobić? • Dodać biblioteki do projektu • Dodać spis dodanych biblioteki do pliku deployed-jars-ear.list • EWENTUALNIE DODAĆ do pliku web.xml odpowiednie wpisy – definiowanie wzorca url dla naszych zapytań restowych • Utworzyć obiekt z odpowiednią adotacją • Utworzyć w obiekcie metodę odpowiadającą na zapytanie restowe • Cieszyć się z API restowego w naszej aplikacji
Opis klasy jako usługi REST Klasa, która będzie wystawiać usługę typu REST powinna posiadać adnotację @javax.ws.rs.Path ze wskazaniem ścieżki pod jaką będzie widoczna usługa. Dodatkowo wskazujemy metodę, która będzie się wykonywać w momencie wywołania. Do tego celu wykorzystujemy adnotacje:@GET (lub@POST, @HEAD, @PUT, itd.) z pakietu javax.ws.rs. Dzięki temu możemy określić różne metody dla różnych typów wywołań (GET/POST/PUT/HEAD/...) REST'a. @javax.ws.rs.Produces z określeniem w jakim formacie będzie prezentowany wynik. Do dyspozycji mamy dwa popularne formaty: json ("application/json") i xml ("text/xml").
JSON – javascriptobjectnotation • JSON - lekki format wymiany danych komputerowych. JSON jest formatem tekstowym, będącym podzbiorem języka JavaScript. Typ MIME dla formatu JSON to application/json. { „nazwa”:”Jakas nazwa”, „wartosc”:150, „lista”:[{„1”,”2”,”3”}]. „obiekt”:{„nazwa”:”nazwa1”,”kod”:15} }
JSON i XML {"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } }} <menu id="file" value="File"> <popup> <menuitem value="New" onclick="CreateNewDoc()" /> <menuitemvalue="Open" onclick="OpenDoc()" /> <menuitem value="Close" onclick="CloseDoc()" /> </popup> </menu>
Przykład klasy odpowiadającej na zapytanie restowe @Path("configResource") @Name("configResource") public class ConfigResource extends SecurityInvoiceResource { @In(create = true) ConfigResourceActionconfigResourceAction; @GET @Path("/config/{invoiceId}") @Produces({ MediaType.APPLICATION_JSON }) public Response getEditorConfiguration(@PathParam("invoiceId") final long invoiceId) { if (correctStatus(getInitStatus()) && correctRole(invoiceId)) { return buildResponse(configResourceAction.getConfiguration(invoiceId)); } return buildResponse(getInitStatus()); } } Adres do odwołania się do usługi: ../configResource/config/123
Jak to teraz połączyć z angularjs Zapisz() Pobierz()
Service & Factory Tych elementów angulara używamy zazwyczaj do definiowania modelu(danych) w MVC czyli jak i skąd mamy pobierać dane dla naszej aplikacji. Serwisy i fabryki używane są do wymiany danych między kontrolerami dzięki bardzo prostemu mechanizmowi wstrzykiwania zależności.
functionHelloCtrl($scope, testService, testFactory) { $scope.fromService = testService.sayHello("World"); $scope.fromFactory = testFactory.sayHello("World"); } functionGoodbyeCtrl($scope, testService, testFactory) { $scope.fromService = testService.sayGoodbye("World"); $scope.fromFactory = testFactory.sayGoodbye("World"); } app.factory('testFactory', function(){ return { sayHello: function(text){ return "Factorysays \"Hello " + text + "\""; }, sayGoodbye: function(text){ return "Factorysays \"Goodbye " + text + "\""; } } }); app.service('testService', function(){ this.sayHello= function(text){ return "Service says \"Hello " + text + "\""; }; this.sayGoodbye = function(text){ return "Service says \"Goodbye " + text + "\""; }; }); Różnica polega na tym, że serwis zwraca funkcję z parametru, a fabryka obiekt zwracany przez funkcję z parametru.
Wykorzystanie $http i $resource app.factory('ConfigService', function($resource) { return $resource('/seam/resource/rest/configResource/config/:invoiceHeaderId', {invoiceHeaderId:'@invoiceHeaderId'}); }); { 'get': {method:'GET'}, 'save': {method:'POST'}, 'query': {method:'GET', isArray:true}, 'remove': {method:'DELETE'}, 'delete': {method:'DELETE'} }; Dodatkowe metody obiektu zwracanego przez $resource $scope.config = ConfigService.get({invoiceHeaderId:$routeParams.id}, function(){console.log(„Udane pobranie”)}, function(data){console.log(„Błąd”)});
AngularJS HTTP JBOSS + RESTEASY View Factory Rest RestAction Controler Seam business
AppJS AngularJS HTTP JBOSS + RESTEASY View Factory Rest RestAction Controler Seam business
Struktura Dużego projektu Angularjs root-app-folder index.html scripts controllers main.js ... directives myDirective.js ... filters myFilter.js ... services myService.js ... libs angular.js angular.min.js app.js styles ... views main.html ...
Przydatne linki, książki i narzędzia • Strona domowa: http://angularjs.org • Przydatne linki: https://egghead.io/lessons - zbiór video tutoriali • https://leanpub.com/recipes-with-angular-js/read#leanpub-auto-introduction – zbiór przykładów zastosować AngularJS • Książki – „AngularJS” (O’REILLY) i pdf „AngularJS In 60 Minutes” dodane do źródeł • Narzędzia: AngularJSBaratang – do debugowania aplikacji • Narzędzia do testowania - Jasmine