Dyrektywy własne

W rozdziale Dyrektywy wbudowane omawialiśmy te dyrektywy, które są dostarczane bezpośrednio przez framework. Teraz przyszedł czas na prawdziwą zabawę, czyli tworzenie własnych dyrektyw i wplatanie ich w kod HTML.

Dyrektywy w AngularJS tworzymy używając funkcji directive:
angular.module('appa.form').directive('appaFormCategories', function() {
    
    return {
        templateUrl : 'appaform/appa-item-form/categories/appa-form-categories.html'
    };
    
});
Widzimy, że aby zdefniować dyrektywę musimy podać jej nazwę oraz funkcję zwracającą obiekt konfiguracyjny. W ramach obiektu możemy ustawiać różne własności. Zaczynamy od pokazania prostego przykładu z użyciem tylko własności templateUrl, wskazującej na szablon z kodem HTML, który ma zostać wstawiony w miejscu użycia dyrektywy.

Załóżmy teraz, że zawartość pliku appa-form-categories.html zawiera kod umożliwiający stworzenie listy wielokrotnego wyboru:
<label
    class="control-label col-md-2"
    for="category"
    ng-click="uiMultiselectClick()">Category:</label>
<div
    class="col-md-9"
    ng-class="{'has-error' : submitted && appaForm.category.$invalid}">
    <ui-select multiple ...> 
        ...
    </ui-select>
</div>
<div class="col-md-1 ...">
    <button
    	class="btn btn-default ..."
    	ng-click="clearAppaCategories()">
    	<image ng-src="appaform/assets/cross_close.png" />
    </button>
</div>
Po użyciu naszej dyrektywy w ten sposób:
<appa-form-categories></appa-form-categories>
kod HTML zawarty w pliku zostanie wstawiony w miejsce naszego tag-a i tak też będzie ostatecznie interpretowany przez przeglądarkę.

Rodzaje dyrektyw

To w jaki sposób będziemy mogli używać dyrektywy zależy przede wszystkim od tego jaki jej rodzaj wybierzemy. Mamy do dyspozycji cztery możliwości. Zobaczmy jak będą one wyglądać, gdy przyjmiemy za przykład naszą dyrektywę podaną we wstępie:
  • Nazwa elementu (Element name)
    <appa-form-categories></appa-form-categories>
    
  • Atrybut (Attribute)
    <div appa-form-categories></div>
    
  • Klasa (Class)
    <div class="appa-form-categories"></div>
    
  • Komentarz (Comment)
    <!-- directive: appa-form-categories -->
    
Jak pewnie zauważyliście nazwa podana przez nas w funkcji directive w postaci camelCase, jest zamieniana w widoku w ten sposób, że każdą duża literę występującą po małej, zastępuje myślnik z małą literą.

Stworzona przez nas dyrektywa może być użyta zarówno jako nazwa elementu jak i atrybut. Wynika to z tego, że domyślnie każda dyrektywa jest określona z restrykcją EA, która oznacza nie mniej, nie więcej jak:

E - Element name
A - Attribute

Jeżeli chcemy mieć wpływ na to jak ma być używana dyrektywa, to możemy skorzystać w tym celu z własności restrict. Przyjmuje ona następujące wartości:
  • E - dla Nazwy elementu (Element name)
  • A - dla Atrybutu (Attribute)
  • C - dla Klasy (Class)
  • M - dla Komentarza (Comment)
Przykładowo jeśli chcemy aby nasza dyrektywa mogła być używana tylko w postaci elementu, to wówczas jej definicja będzie wyglądała tak:
angular.module('appa.form').directive('appaFormCategories', function() {
    
    return {
        restric t : "E",
        templateUrl : 'appaform/appa-item-form/categories/appa-form-categories.html'
    };
    
});
Ten rodzaj dyrektyw jest najbardziej czytelny i stosunkowo najprostszy. Stanowi on dobry wstęp do dalszej pracy z dyrektywami.

Zakres dyrektyw (scope)

Domyślnie każda dyrektywa otrzymuje dostęp do zakresu swojego rodzica (parent's scope), a więc zmiana obiektu przekazanego do dyrektywy zmienia ten obiekt u źródła (referencja wskazuje na ten sam obiekt). Zachowaniem tym możemy sterować, co zresztą jest to dosyć powszechnie stosowane. Dokonujemy tego za pomocą odpowiedniego ustawienia własności scope. W przypadku gdy chcemy odizolować dyrektywę od rodzica, ustawiamy tą własność na true. W przeciwnym wypadku nie musimy robić nic, gdyż false jest ustawieniem domyślnym.
angular.module('appa.form').directive('appaFormCategories', function() {
    
    return {
        scope: true,
        restric t : "E",
        templateUrl : 'appaform/appa-item-form/categories/appa-form-categories.html'
    };
    
});
Jeśli zdarza się tak (a zdarza się dosyć często), że chcemy odizolować kontekst dyrektywy od kontekstu rodzica, a jednak musimy przesłać dane do naszej dyrektywy, to wtedy na ratunek przychodzi nam możliwość podania w tym miejscu obiektu konfiguracyjnego (zamiast zwykłej flagi). W obiekcie tym będziemy mogli określać parametry oraz sposób ich przekazywania do dyrektywy. Odpowiedzialne będą za to specjalne atrybuty dopasowujące, takie jak @ czy =. Niemniej o tym będziemy mówić już w kolejnych rozdziałach...
angular.module('appa.form').directive('appaFormCategories', function() {
    
    return {
        scope: {
            ...
        },
        restric t : "E",
        templateUrl : 'appaform/appa-item-form/categories/appa-form-categories.html'
    };
    
});
W tym rozdziale przedstawiliśmy podstawowe zagadnienia związane z dyrektywami w AngularJS. Są one wystarczające aby zrozumieć czym są dyrektywy i co możemy dzięki nim osiągnąć stosując je w podstawowej formie. W kolejnym rozdziale postaramy się przyjrzeć temu tematowi jeszcze dokładniej i przeanalizujemy nieco bardziej zaawansowane przykłady konfiguracji i wykorzystania dyrektyw. Szczególnie interesujące jest użycie atrybutów dopasowujących, które określają sposób wiązania danych pomiędzy dyrektywą a komponentem, w którym ta dyrektywa jest umieszczona.
Rekomendacja
Tworzenie własnych dyrektyw przydaje się w szczególności gdy potrzebujemy komponentów wielokrotnego użytku. Przygotowujemy wtedy w jednym miejscu komponent zawierający zarówno kod HTML jak i Javascript, by następnie w prosty sposób wstawiać go w innych miejscach w aplikacji. Zmieniając zachowanie komponentu w jednym miejscu, wpływamy na jego zmianę wszędzie tam gdzie jest on użyty.

Dodatkowo wprowadzając część kodu do dyrektyw powodujemy, że kod całej aplikacji staje się bardziej uporządkowany, a przez to także bardziej czytelny. Pamiętajmy jednak aby też nie popadać w skrajności i nie używać dyrektyw gdzie tylko się da. Taki kod w przyszłości może powodować spore ograniczenia w wypadku zmiany wymagań projektowych, bądź też gdy zaistnieje potrzeba rozbudowy tego samego komponentu w różnych kierunkach, w zależności od miejsca jego użycia.
Używamy w StartAPPa


W aplikacji stworzyliśmy wiele własnych dyrektyw. W szczególności są one używane do budowy formularza do dodawania i edycji itemów. Znajdziemy tam dyrektywy takie jak:
  • appa-form-date-common
  • appa-form-date-from
  • appa-form-date-to
  • appa-form-types
  • appa-form-categories (to jej fragmenty pokazaliśmy w tym rozdziale)
  • appa-form-statuses
  • appa-form-attributes
  • input-focus-function
  • appa-form-preview
Kod całego rozwiązania jest dostępny w ramach znanego Wam już zapewne kursu Formularz Zaawansowany.

Inny kurs, w którym wykorzystaliśmy dyrektywy to Formularz Podstawowy. W nim znajdziecie dyrektywy:
  • appa-users
  • compare-to - porównuje pod kątem zgodności wprowadzane hasło z hasło powtórzonym
 
Ponadto w każdym z kursów wykorzystujemy również bardzo proste, ale użyteczne dyrektywy:
  • navbar - wstawia nagłówek na stronie
  • loader - pokazuje kręcące się kółeczko podczas wykonywania operacji w tle
Linki:
https://docs.angularjs.org/api/ng/service/$compile#directive-definition-object

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE