Wpis ten, będzie związany z komponentami oraz ich implementacją w AngularJS. Przedstawię zalety pisania w oparciu o ten sposób tworzenia aplikacji. Omówię tworzenie komponentów wraz ze wszystkimi możliwościami konfiguracji. A także, utworzymy razem prostą aplikację, służącą do robienia listy zakupów, przykład ten idealnie pokazuje idee tworzenia aplikacji w oparciu o komponenty.
Trochę teorii
Komponenty to uproszczone w tworzeniu dyrektywy (o nich będzie mowa już niedługo). Dyrektywa to znacznik napisany przez osobę tworzącą aplikację, posiadająca własny wygląd oraz przyjmowane atrybuty. Pojawiły się wraz z wydaniem wersji AngularJS 1.5. Aplikacje tworzone za pomocą component przypominają wykorzystywanie Web Components, czy pisania aplikacji w wersji Angular 2.
Zaletami tego rozwiązania są: prosta konfiguracja, tworzenie aplikacji w oparciu o komponenty oraz możliwość prostrzego przejścia na nowsze wersję frameworka.
Obiekt konfiguracyjny składa się z kilku atrybutów, które pokrótce omówię.
bindings – dane przekazane za pomocą atrybutów w kodzie html. Wyróżniamy kilka znaków, które określają typ przekazywanych danych:
@ – oznacza, że w atrybucie zostanie wprowadzony ciąg znaków.
= – wiązanie dwukierunkowe, czyli, gdy wprowadzona dana zostanie zmieniona, to zmiana również nastąpi w miejscu z którego została załadowana do komponentu.
< – wiązanie jednokierunkowe, wprowadzane zmiany następują jedynie w obrębie komponentu.
& – oznacza, że przekazana zostanie funkcja.
controller – funkcja, która jest kontrolerem dyrektywy. Domyślnie przy wywołaniu w pliku html korzystamy z $ctrl.
template – wygląd opisany za pomocą ciągu znaków.
templateUrl – wygląd opisany za pomocą dodatkowego pliku.
Aplikacja – Lista zakupów
Tym razem utworzymy prostą aplikację do zarządzania listą zakupów. Powstanie z wykorzystaniem komponentów. Zostaną utworzone cztery komponenty. Kod html każdego elementu będzie w osobnym pliku.
Kod pliku index.html
<!DOCTYPE html> <html lang="pl" ng-app="app"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>AngularJS #9</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> .panel-default { margin-top: 2em; padding: 1em; } .btn { width: 100% } .control-form { width: 100% } .inupt-text { margin-bottom: 1em; width: 100%; } </style> </head> <body> <title-page title="AngularJS #9"></title-page> <div class="row"> <div class="col-md-4 col-md-offset-4 panel panel-default"> <shop-list></shop-list> </div> </div> <script src="https://code.jquery.com/jquery-3.2.1.slim.js" integrity="sha256-tA8y0XqiwnpwmOIl3SGAcFl2RvxHjA8qp0+1uCGmRmg=" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script> <script> var app = angular.module("app", []); app.component('titlePage', { templateUrl: 'titlePage.html', bindings: { title: '@' } }); app.component('shopList', { templateUrl: 'shopList.html', controller: shopListController }); app.component("item", { templateUrl: 'item.html', bindings: { data: '=' } }); app.component("newItem", { templateUrl: 'newItem.html', bindings: { new: '&' }, controller: newItemController }); function shopListController () { var ctrl = this; ctrl.list = [{ name: "apple", checked: false }, { name: "milk", checked: true }]; ctrl.addItem = function (name) { ctrl.list.push({name: name, checked: false}); } } function newItemController () { var ctrl = this; ctrl.add = function (name) { ctrl.new({name: name}); ctrl.newName = ''; } } </script> </body> </html>
Kod pliku titlePage.html
<h1 class="text-center">{{$ctrl.title}}</h1>
Kod pliku shopList.html
<item data="item" ng-repeat="item in $ctrl.list"></item> <new-item new="$ctrl.addItem(name)"></new-item>
Kod pliku item.html
<p> <input type="checkbox" ng-model="$ctrl.data.checked" />{{$ctrl.data.name}} </p>
Kod pliku newItem.html
<input class="group-form inupt-text" type="text" ng-model="$ctrl.newName"/> <button class="btn btn-default" ng-click="$ctrl.add($ctrl.newName)">ADD</button>
Wykorzystamy do utworzenia aplikacji szablon strony, który można było zobaczyć we wcześniejszych wpisach. Jak możemy zobaczyć, kod index.html zawiera dyrektywę <title-page> oraz <shop-list>.
Przejdźmy zatem do kody JS. Po utworzeniu modułu AngularJS, przystepujemy do utworzenia pierwszego komponentu, którym jest title-page. Pierwszym parametrem metody component jest nazwa znacznika titlePage (duża litera P oznacza, że w pliku html wywołamy ten komponent używając <title-page>), następnym zaś obiekt konfiguracyjny. Dokładnie, w tym przypadku wykorzystywany jest obiekt, a nie jak w innych przypadkach np. kontrolerach funkcja tworząca. Obiekt dla tego komponentu zawiera dwie właściwości: templateUrl oraz bindings. TemplateUrl wskazuje na plik odpowiedzialny za wygląd utworzonego znacznika, zaś bindings za przyjmowane atrybuty. W tym przypadku mamy jeden atrybut o nazwie title, który przyjmuje ciąg znaków. Komponent ten, odpowiedzialny będzie za wyświetlenie wyśrodkowanej nazwy aplikacji na środku strony.
Kolejną dyrektywą, którą utworzymy jest <shop-list>. Tworzymy ją w podobny sposób jak poprzednią, tym razem jednak dodajemy kontroler jako funkcję o nazwie shopListController napisaną poniżej w kodzie JS. W kodzie kontrolera tworzona jest zmienna odnosząca się do obiektu funkcji ctrl. Do tej zmiennej dodawane jest pole reprezentujące listę zakupów będące tablicą, a także funkcja dodająca do tej tablicy dane. Przechodząc do pliku shopList.html widzimy dwa nowe komponenty: <item> oraz <new-item>. Pierwszy odpowiada za wyświetlanie listy produktów do kupienia, drugi zaś za dodawanie nowych danych do tablicy.
Każdy element listy wyświetlany jest za pomocą przekazanego obiektu do znacznika <item> jako atrybut data. Iteracja po obiektach listy odbywa się za pomocą atrybutu ng-repeat. Przejdźmy teraz do kodu JS odpowiedzialnego za implementację tego komponentu. W obiekcie konfiguracyjnym przekazujemy jedynie obiekt data.
Ostatni komponent, odpowiada za dodawanie elementów do listy. W obiekcie konfiguracyjnym mamy dwie właściwości. Bindings przekazuje funkcję dodającą, natomiast kontroler wskazuje na funkcję newItemController. W kontrolerze następuje utworzenie zmiennej ctrl, do której przypisana jest funkcja add() implementująca przekazaną funkcję przez atrybut. Funkcja add() wywołana jest w pliku newItem.html za pomocą atrybutu ng-click dla przycisku. Jedyne na co musimy zwrócić uwagę to wywołując przekazaną funkcję przez atrybut należy parametr przypisać za pomocą obiektu {nazwa parametru z atrybutu: wartość jaka ma zostać pobrana}.
Efekt działania aplikacji
Podsumowanie
W tym wpisie udało się nam omówić działanie komponentów w AngularJS. Sposób ich tworzenia oraz pokazać na przykładzie prostej aplikacji jak wykorzystywać możliwości jakie dają komponenty. Przedstawiony został obiekt konfiguracyjny wraz z polami jakie w nim występują. W kolejnym wpisie, zajmiemy się kolejnymi elementami tego frameworka.
One thought on “AngularJS – Component”