tutorial-angularJS

Tutorial AngularJS: tworzymy pierwszą aplikację

Zaczynamy budowę naszej aplikacji w AngularJS zupełnie od zera. Na początek więc stwórzmy prostą stronę HTML, do której później dołączymy biblioteki AngularJS. Otwórz więc swój ulubiony edytor tekstowy i wpisz następujący kod, a następnie zapisz jako plik HTML:

<!DOCTYPE html>
  <head>
   <meta charset=”UTF-8”>
   <title>Kurs AngularJS</title>
  </head>
  <body>
  </body>
</html>

Jako, że mamy już pusty dokument HTML, który stanowi bazę dla naszej aplikacji, czas podłączyć pod niego framework AngularJS. Wchodzimy na stronę https://angularjs.org/ i klikamy DOWNLOAD. Kopiujemy link z okienka w polu CDN (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js) i dołączamy go jako zewnętrzny skrypt do naszej strony w części<head></head>.

<!DOCTYPE html>
<head>
    <meta charset=”UTF-8”>
    <title>Kurs AngularJS</title>
    <script type=”text/javascript” src=”https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js”></script>
</head>
<body>
</body>
</html>

Okej, teraz możemy już zacząć używać AngularJS na naszej stronie. Najpierw musimy jednak wyraźnie zaznaczyć, w którym miejscu będziemy używać tego frameworka. Robimy to poprzez dodanie zbiorczego bloku div i nadajemy mu atrybut ng-app. Ten atrybut jest tzw. dyrektywą AngularJS. W dalszej części naszej aplikacji zobaczysz inne atrybuty zaczynające się od ng-, one wszystkie są dyrektywami, czyli niejako poleceniami AngularJS. Dyrektywa ng-app mówi, że będziemy w tym miejscu korzystać z kodu AngularJS. Opcjonalnie możemy podać jej wartośc, która będzie nazwą aplikacji – jest to przydatne szczególnie w zaawansowanych projektach. Ja użyłem „PremierySeriali”. Od razu dodałem też klasę „container”, która przyda nam się później, gdy do naszej aplikacji podłączymy Bootstrapa.

<!DOCTYPE html>
<head>
    <meta charset=”UTF-8”>
    <title>Kurs AngularJS</title>
    <script type=”text/javascript” src=” https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js”></script>
</head>
<body>
    <div class="container" ng-app=’PremierySeriali’>
    </div>
</body>
</html>

No dobra, mamy już stronę przygotowaną pod naszą aplikację „PremierySeriali”. Ale gdzie właściwie znajduje się ta aplikacja? No właśnie, musimy ją stworzyć! Otwieramy ulubiony edytor tekstowy i tworzymy nowy plik aplikacja.js. W środku wpisujemy kod:

var apka = angular.module('PremierySeriali',[]);

I zapisujemy plik. Pamiętaj, aby plik aplikacja.js zapisać w tym samym folderze, co plik html. Powyzszy kod tworzy moduł angular, który będzie zawierał naszą aplikację. Ma taki sam tytuł, jak użylismy w pliku html (PremierySeriali) i przypisuje go do nowej zmiennej apka. Moduły, jak pewnie się domyślasz, pozwalają dzielić naszą aplikację na części, a każda część zajmuje się np. inną funkcjonalnością. Do potrzeb tego tutoriala wystarczy nam jeden moduł.

Zanim przystąpimy do kolejnego kroku, warto nadmienić, ze AngularJS jest frameworkiem działajacym w oparciu o architekturę MVC, czyli Model – View – Controller. Czym jest każda z tych części? Najłatwiej myśleć o Modelu jako o zestawie danych – większość dynamicznych aplikacji webowych opiera się właśnie na danych. W AngularJS możemy oczywiście sami rozpisać nasze dane w pliku, ale najczęściej wykorzystuje się połączenia z istniejącymi bazami danych lub plikami JSON. Dane wyświetlamy użytkownikom za pomocą kolejnej części architektury MVC, mianowicie View. Można porównać View (widok) do szablonu dla wyświetlanych danych. W AngularJS tworzymy widoki informacji (Views) poprzez umieszczanie podwójnych nawiasów klamrowych {{}} w kodzie HTML. Ostatnią częścią architektury są Kontrolery, które stanowią pomost między modelem a widokiem. Kontroler pozwala wzbogacić zestaw danych w modelu o jakieś funkcjonalności. Tworzymy więc kolejny plik, w którym umieścimy kontroler, którego będziemy używać do przeprowadzania operacji na danych:

apka.controller("MojController", function($scope,$http){
});

Nazwijmy ten plik kontroler.js I również umieśćmy w folderze z naszą aplikacją. Powyższy plik przypisuje kontroler MojController do aplikacji „apka”. Zamiast tworzyć oddzielny plik .js na kontroler, mogliśmy umieścić wszystko w jednym pliku, ale myślę, że powinniśmy pielęgnować troskę o czytelność kodu, bez względu czy to tutorial czy oficjalna aplikacja. Zatem połączmy dwa stworzone właśnie pliki, aplikacja.js oraz kontroler.js z plikiem html, a utworzony kontroler dodajmy do naszego elementu div#container za pomocą dyrektywyng-controller:

<!DOCTYPE html>
<head>
    <meta charset=”UTF-8”>
    <title>Kurs AngularJS</title>
    <script type=”text/javascript” src=” https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js”></script>
    <script src="aplikacja.js" type="text/javascript"></script> <!-- aplikacja angularJS -->
<script src="kontroler.js" type="text/javascript"></script> <!-- glowny controller przypisany do aplikacji AngularJS -->
</head>
<body>
    <div class="container" ng-app=’PremierySeriali’ ng-controller='MojController'>
    </div>
</body>
</html>

Teraz możemy już korzystać z kontrolera w naszej aplikacji, a konkretnie w elemencie div #container. Sprawdźmy, czy to działa. W pliku kontroler.js, być może zauważyłeś, gdy tworzyliśmy kontroler, od razy stworzyliśmy funkcję $scope. Utwórzmy przykładową zmienną w tej funkcji:

apka.controller("MojController", function($scope,$http){
    $scope.mojtekst = "Witaj w mojej aplikacji AngularJS!";
});

i spróbujmy się do niej odwołać w naszym pliku html przy pomocy nawiasów klamrowych:

...
<div class="container" ng-app=’PremierySeriali’ ng-controller='MojController'>
    {{mojtekst}}
</div>
...

Jeśli wszystko zrobiliśmy, jak trzeba, przeglądarka powinna wyrenderować tekst:

kurs-angularjs-tutorial Wszystko gra, a więc możemy przystąpić do kolejnego kroku.

Zaciągamy dane do aplikacji

Okej, jak wspomniałem na wstępie, nasza aplikacja będzie wyświetlała nowości serialowe. Potrzebujemy więc danych o tych serialach. Skorzystamy z API serwisu www.themoviedb.org. Aby korzystać z API, potrzebny nam jest klucz. Aby otrzymać klucz API, należy założyć (darmowe) konto na stronie themoviedb.org i wejść do zakładki API.

Klucz jest nam potrzebny, aby nie tracić czasu na ręczne tworzenie bazy danych po stronie naszego serwera, a także aby bazować na rzetelnych informacjach z serwisu, który na co dzień zajmuje się kinematografią. W ten sposób możemy założyć, że nasza aplikacja po ukończeniu będzie rzeczywiście użyteczna.

Po zdobyciu klucza do API, dodajemy go do naszego kontrolera. Wchodzimy do pliku kontroler.js i usuwamy poprzednią zadeklarowaną zmienną mojetekst, na jej miejsce tworzymy nową, która przechowywać będzie nasz klucz API:

apka.controller("MojController", function($scope,$http){
    $scope.kluczApi = "...";  // wstaw swój klucz api - np. d9eb45644e9.....
});

Lektura dokumentacji API serwisu themoviedb.org dostarcza nam informacji, jak stworzyć odwołanie, które prześle nam dane potrzebne do naszej aplikacji. Chodzi mianowicie o odwołanie ‘ first_air_date.gte‘, które pozwoli nam otrzymać seriale, które pierwszy raz pojawiły się w telewizji po wpisanej przez nas dacie. API oczekuje daty w formacie YYYY-MM-DD. Nasza aplikacja ma wyświetlać nowości, które pojawiły się w telewizji w tym miesiącu, musimy więc jeszcze określić, jaki dzisiaj jest miesiąc.

var dzisiaj = new Date();
var miesiac = dzisiaj.getFullYear() + “-“ + (“0” + (dzisiaj.getMonth() + 1)).slice(-2) + “-“ + (“0” + dzisiaj.getDate()).slice(-2);

W powyższym kodzie najpierw pobieramy dzisiejszą datę za pomocą JavaScriptowej funkcji ‘Date()‘, następnie wykorzystujemy ją w odpowiedni sposób w zmiennej ‘var miesiąc‘ aby uzyskać datę w wymaganym formacie.

Następnie wykorzystujemy tę zmienną do odwołania się do API za pomocą ‘$http.jsonp‘:

$http.jsonp("https://api.themoviedb.org/3/discover/tv?first_air_date.gte=" + miesiac + "&sort_by=popularity.desc&api_key=’+kluczApi+’&callback=JSON_CALLBACK").success(function(data) {

})

Ubieramy wszystko w funkcję ‘glowna‘ i w efekcie nasz plik ‘kontroler.js‘ powinien wyglądać tak:

apka.controller(„MojController”, function($scope,$http){
    $scope.kluczApi = „...”;  // wstaw swój klucz api - np. d9eb45644e9.....
    $scope.glowna = function() {
        var dzisiaj = new Date();
        var miesiac = dzisiaj.getFullYear() + “-“ + (“0” + (dzisiaj.getMonth() + 1)).slice(-2) + “-“ + (“0” + dzisiaj.getDate()).slice(-2);
        $http.jsonp("https://api.themoviedb.org/3/discover/tv?first_air_date.gte=" + miesiac + "&sort_by=popularity.desc&api_key=’+$scope.kluczApi+’&callback=JSON_CALLBACK").success(function(dane) {

        }).error(function(error) {
            alert(‘Houston, mamy problem z uzyskaniem danych.’);
        });
    };
});

Jak widzisz, wzbogaciłem adres odwołania do API o ciąg &sort_by=popularity.desc. Dzięki temu lista seriali, którą otrzymamy będzie posortowana pod kątem popularności serialów. Na koniec ciągu dodajemy jeszcze zmienną &callback=JSON_CALLBACK, aby upewnić się, że odpowiedź serwera będzie w formacie JSON.

Jeśli chcesz sprawdzić „na sucho” odwołanie do API, wstaw link prosto do przeglądarki, wpisując jakąś datę (na skrinie poniżej jest to 2014-09-01). Powinieneś otrzymać czystą odpowiedź w formacie JSON:

nauka-angularjs

Na jej podstawie możemy stwierdzić, jakie dane o każdym serialu otrzymamy w ramach odpowiedzi z serwera: "id" "original_name" "first_air_date" "origin_country" "poster_path" "popularity" "name" "vote_average" "vote_count"

Dodałem jeszcze alert na wypadek, gdyby nie udało się wykonać połączenia z API. Otrzymane z API dane musimy jeszcze gdzieś przechować. Zadeklarujmy tablicę w obrębie funkcji $scope:

$scope.wyniki = [];

Następnie wykorzystajmy tablicę do zgromadzenia danych z API:

$scope.wyniki = dane.results;

Po tych modyfikacjach plik kontroler.js przedstawia się następująco:

apka.controller(„MojController”, function($scope,$http){
    $scope.kluczApi = "...";  // wstaw swój klucz api - np. d9eb45644e9.....
    $scope.wyniki = [];
    $scope.glowna = function() {
        var dzisiaj = new Date();
        var miesiac = dzisiaj.getFullYear() + “-“ + (“0” + (dzisiaj.getMonth() + 1)).slice(-2) + “-“ + (“0” + dzisiaj.getDate()).slice(-2);
        $http.jsonp("https://api.themoviedb.org/3/discover/tv?first_air_date.gte=" + miesiac + "&sort_by=popularity.desc&api_key=’+$scope.kluczApi+’&callback=JSON_CALLBACK").success(function(dane) {
            $scope.wyniki = dane.results;
        }).error(function(error) {
            alert("Houston, mamy problem z uzyskaniem danych.");
        });
    };
});

Wyświetlamy pobrane dane

Czas wyświetlić informacje o serialach w naszej aplikacji. Wracamy do pliku html i dodajemy atrybut ng-init z nazwą naszej głównej funkcji do div.container. W ten sposób upewniamy się, że ta funkcja będzie wywołana jako pierwsza z naszej angularnej aplikacji po wyświetleniu strony. W elemenciediv.container’ powinieneś mieć odwołanie do naszej testowej zmiennej{{mojtekst}}`. Usuń więc je.

<div class="container" ng-app='PremierySeriali' ng-controller='MojController' ng-init='glowna()'>
    {{mojtekst}}  <!--- <-kasujemy -->
</div>

Teraz bierzemy się za wyświetlenie danych na naszej stronie. Skorzystamy z dyrektywy ng-repeat, która pozwoli nam dynamicznie wyświetlić zawartość danych w tablicy wyniki[] jako np. listę. Gotowy kod wygląda tak:

<div class="container" ng-app='PremierySeriali' ng-controller='MojController' ng-init='glowna()' >
    <div class="row">
        <div class="col-md-2" ng-repeat='serial in wyniki'>
        <h2>{{serial.original_name}}</h2>
        </div>
    </div>
</div>

Po uruchomieniu w przeglądarce, otrzymujemy listę serialowych premier miesiąca. W moim przypadku wygląda tak:

jak-stworzyc-projekt-w-angularjs

Zanim dodamy nowe funkcjonalności, ubierzmy naszą aplikację w estetyczne wdzianko. Najlepiej sprawdzi się Boostrap, popularny framework, umożliwiający szybkie tworzenie projektów stron, także responsywnych. Pobieramy Bootstrapa i dodajemy go do naszej strony, tworząc także prosty szablon za pomocą obecnych w Bootstrapie gotowych modułów. Nie będę się rozwodził nad nimi w szczegółach w tym tutorialu, wszak skupiamy się tu na AngularJS.

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Kurs AngularJS</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
    <script src="aplikacja.js" type="text/javascript"></script> <!-- aplikacja angularJS -->
    <script src="kontroler.js" type="text/javascript"></script> <!-- glowny controller przypisany do aplikacji AngularJS -->

    <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"><!-- bootstrap -->
    <link rel="stylesheet" type="text/js" href="css/bootstrap.min.js"><!-- bootstrap -->

</head>
<body>

    <div class="navbar navbar-inverse" role="navigation">
        <div class="container">
            <div class="navbar-header">
              <a class="navbar-brand" href="#">Serialowe nowości</a>
            </div>
        </div>
    </div>

    <div class="container" ng-app='PremierySeriali' ng-controller='MojController' ng-init='glowna()' >
        <div class="row">
            <div class="col-md-2" ng-repeat='serial in wyniki'>
                <img ng-show="serial.poster_path != null" src="https://image.tmdb.org/t/p/w185{{serial.poster_path}}" style="height:272px" />
                <img ng-show="serial.poster_path == null" src="images/brak-postera.jpg" />
                <h2>{{serial.original_name}}</h2>
            </div>
        </div>
    </div>
</body>
</html>

Ponadto, posługując się zmienną serial.poster_path możemy wyświetlić plakat do każdego serialu. Jeśli plakatu nie ma w otrzymanym z API zestawie danych, wyświetlamy informującą o tym grafikę. Odpowiada za to dyrektywa ng-show, która sprawdza, czy serial.poster_path istnieje, a następnie wyświetla stosowny <img>. Drobnym kłopotem jest fakt, że plakaty niektórych seriali w bazie themoviedb.org mają większą wysokość od pozostałych, co czasem może powodować rozjeżdzanie się naszej aplikacji, która wyświetla seriale w formie siatki. Rozwiązaniem jest utrzymanie stałego rozmiaru plakatów za pomocą atrybutu style="height:272px dla tagu img.

Gotowa aplikacja powinna wyglądać mniej więcej w poniższy sposób. Wyświetlane są premierowe seriale w danym miesiącu, a zawartość zmienia się dynamicznie w zależności od tego, jaki aktualnie mamy miesiąc – bazując na danych z API serwisu themoviedb.org.

tutorial-angularjs-od-podstaw

Jestem ciekaw, jak rozwiniesz swoją aplikację – samo API daje jeszcze sporo możliwości rozbudowy naszej angularnej apki o nowe funkcjonalności. Zachęcam do eksperymentowania – wszyscy wiemy, że to najlepszy sposób na naukę.