W tym wpisie zostaną omówione podstawowe dyrektywy, których jeszcze nie używaliśmy podczas nauki omawianego frameworka. We wcześniejszych materiałach korzystaliśmy z kilku dyrektyw wbudowanych w AngularJS, były to: ng-app, ng-controller, ng-repeat, ng-click, ng-model. Napisana przez nas aplikacja wyglądem będzie przypominała te z wcześniejszych wpisów, jednak tym razem pokażę użycie nowych dyrektyw.
Dyrektywy
Ng-bind
Dyrektywa ta odpowiada za wiązanie danych, często jest zastępowana przez interpolację, czyli parę {{ }} np. {{ $ctrl.name }}. Zaletą stosowania tej dyrektywy jest pozbycie się problemu występującego podczas ładowania strony, kiedy to zamiast odpowiednich danych na stronie wyświetlane są klamerki wraz z wyrażeniami np. {{ $ctrl.name }}.
<h1 class="text-center" ng-bind="$ctrl.name"></h1>
Ng-cloak
Umożliwia osiągnięcie podobnego efektu jak za pomocą dyrektywy ng-bind podczas ładowania strony, gdy korzystamy z interpolacji (klamerek {{}}). Ważne jest aby dodać kod css, bez tego nie zobaczymy oczekiwanego rezultatu. Działa na elemencie do którego została dodana oraz na jego dzieciach. Można ją dodać do znacznika body, tak aby cała aplikacja z niej korzystała.
Klasa css
[ng\:cloak], [ng-cloak], .ng-cloak { display: none !important; }
Kod JS
<h2 ng-cloak>{{$ctrl.ngCloak}}</h2>
Ng-bind-html
To rozszerzona dyrektywa ng-bind, która pozwala programiście na wstrzykiwanie kodu HTML do danego elementu. Musimy jednak pamiętać, aby przed jej użyciem dodać do aplikacji moduł angularowy ngSanitize.
To kolejna dyrektywa umożliwiająca wstrzykiwanie kodu html do elementów.
<span ng-bind-html="$ctrl.bindHTML"></span>
Ng-change
Odpowiada za wykonanie określonej operacji po dokonaniu zmiany w polu input. Reaguje na każdą zmianę w tym także usunięcie znaku.
<input type="text" ng-model="$ctrl.inputChange" ng-change="$ctrl.change()">
Ng-class
Daje nam możliwość dodawania klas do elementów pod określonymi warunkami, jeśli warunek jest spełniony nowa klasa zostanie dodana. Możemy jednocześnie dodawać wiele klas.
<span ng-class="{ 'ng-class-true': $ctrl.ngClass, 'ng-class-false': !$ctrl.ngClass }">Dyrektywa ngClass</span> <input type="checkbox" ng-model="$ctrl.ngClass">
Ng-repeat
Z dyrektywy tej już korzystaliśmy niejednokrotnie, jednak nie wspominałem jeszcze o jej wszystkich możliwościach. Iterując po kolekcji mamy dostęp do specjalnych właściwości:
- $index – to numer elementu w zbiorze, zaczyna się od 0 i kończy na n-1,
- $first – zwraca true, jeśli dany element jest pierwszym w kolekcji,
- $middle – zwraca true, jeśli dany element jest między pierwszy, a ostatnim w kolekcji,
- $last – zwraca true, jeśli dany element jest ostatni w kolekcji,
- $even – zwraca true, jeśli $index jest parzysty, w przeciwnym wypadku false,
- $odd – zwraca true, jeśli $index jest nieparzysty, w przeciwnym wypadku false.
<table class="table table-responsive"> <thead> <td>Lp.</td> <td>First Name</td> <td>Last Name</td> </thead> <tr ng-repeat="user in $ctrl.users" ng-class="{ 'table-even': $even, 'table-odd': $odd }"> <td>{{ $index + 1 }}</td> <td>{{ user.firstName }}</td> <td>{{ user.lastName }}</td> </tr> </table>
Ng-dblclick
Pozwala nam określić sposób zachowania elementu po dwukrotnym kliknięciu na jego powierzchnię.
<h1>{{ $ctrl.counter }}</h1> <button type="button" class="btn btn-primary" ng-click="$ctrl.click()">Zwiększ o 1</button> <button type="button" class="btn btn-primary" ng-dblclick="$ctrl.dblclick()">Zwiększ o 2</button>
Ng-href
Tworzy dynamiczne linki zmieniające się pod wpływem interakcji użytkownika z interfejsem.
<a ng-href="http://www.adres.pl/{{$ctrl.counter}}">http://www.adres.pl/{{ $ctrl.counter }}</a>
data-ng-keydown, data-ng-keypress, data-ng-keyup, ng-keyup
Odpowiadają za obsługę klawiatury:
- data-ng-keydown – wykonanie funkcji podczas wciśnięcia przycisku klawiatury,
- data-ng-keypress – wykonanie funkcji podczas wciskania przycisku klawiatury,
- data-ng-keyup – wykonanie funkcji podczas puszczania przycisku klawiatury,
- ng-keyup – pozwala nam na odczytanie kodu wciśniętego przycisku.
<input data-ng-keydown="$ctrl.clog('keydown')" placeholder="keydown"> <br> <input data-ng-keypress="$ctrl.clog('keypress')" placeholder="keypress"> <br> <input data-ng-keyup="$ctrl.clog('keyup')" placeholder="keyup"> <br> <p>Typing in the input box below updates the keycode</p> <input ng-keyup="event=$event"> <p>event keyCode: {{ event.keyCode }}</p> <p>event altKey: {{ event.altKey }}</p>
ng-mousedown, ng-mouseenter, ng-mouseleave, ng-mousemove, ng-mouseover, ng-mouseup
Odpowiadają za obsługę myszy:
- ng-mousedown – odpowiada za wykonanie funkcji po wciśnięciu przycisku myszy,
- ng-mouseenter – odpowiada za wykonanie funkcji po najechaniu myszą na element,
- ng-mouseleave – odpowiada za wykonanie funkcji tuż po opuszczeniu danego elementu,
- ng-mousemove – odpowiada za wykonanie funkcji podczas poruszania myszką po elemencie,
- ng-mouseover – odpowiada za wykonanie funkcji po najechaniu myszą na element,
- ng-mouseup – odpowiada za wykonanie funkcji po puszczeniu przycisku myszy.
Każde zdarzenie wysyła jako parametr obiekt zdarzenia, zapisywany za pomocą $event.
<button class="btn btn-default" ng-mousedown="$ctrl.clog('ngMousedown')" ng-mouseenter="$ctrl.clog('ngMouseenter')" ng-mouseleave="$ctrl.clog('ngMouseleave')", ng-mousemove="$ctrl.clog('ngMousemove')", ng-mouseover="$ctrl.clog('ngMouseover')" ng-mouseup="$ctrl.clog('ngMouseup')">Mysz</button>
ng-readonly
Zadaniem tej dyrektywy jest zmiana pola input na tylko do odczyty w przypadku spełnienia określonych kryteriów. Jeśli wartość jest true, wtedy pole zostanie zablokowane.
<input type="text" ng-readonly="$ctrl.ngRead"> <input type="checkbox" ng-model="$ctrl.ngRead">
ng-style
Dyrektywa ta pozwala programiście na dodawanie styli do wybranego elementu.
<p ng-style="$ctrl.ngStyle">Przykładowy tekst</p>
ng-submit
Określa niestandardowe zachowanie aplikacji w przypadku przesłania formularza, za pomocą przycisku z określonym typem submit.
<form data-ng-submit="$ctrl.submit()"> <input type="text" ng-model="$ctrl.submitText" name="text" /> <input type="submit" class="btn btn-default" id="submit" value="Wyślij" /> </form>
Przykładowa aplikacja
Aplikacja jaką stworzyłem na potrzeby tego wpisu prezentuje wszystkie z omówionych dyrektyw.
Kod JS
var app = angular.module("app", ['ngSanitize']); app.component('appRoot', { templateUrl: 'app-root.html', controller: rootAppController }); function rootAppController() { var ctrl = this; ctrl.name = "Dyrektywy"; ctrl.bindHTML = "Przykładowy kod HTML"; ctrl.ngCloak = "Dyrektywa ngCloak"; ctrl.inputChange = ""; ctrl.change = function () { console.log(ctrl.inputChange); }; ctrl.ngClass = true; ctrl.users = [{ firstName: "Adam", lastName: "Kowalski" }, { firstName: "Kamil", lastName: "Wiśniewski" }, { firstName: "Ania", lastName: "Nowakowska" }, { firstName: "Marek", lastName: "Wójcik" }, { firstName: "Krystyna", lastName: "Nowak" }, ]; ctrl.counter = 0; ctrl.click = function () { ctrl.counter++; }; ctrl.dblclick = function () { ctrl.counter += 2; }; ctrl.clog = function (value) { console.log(value); }; ctrl.ngRead = true; ctrl.ngStyle = { color: 'yellow' }; ctrl.submitText = ""; ctrl.submit = function () { console.log(ctrl.submitText); }; }
app-root.html
<div class="group"> <h1 class="text-center" ng-bind="$ctrl.name"></h1> </div> <div class="group"> <h2 ng-cloak>{{$ctrl.ngCloak}}</h2> </div> <div class="group"> <span ng-bind-html="$ctrl.bindHTML"></span> </div> <div class="group"> <input type="text" ng-model="$ctrl.inputChange" ng-change="$ctrl.change()"> </div> <div class="group"> <span ng-class="{ 'ng-class-true': $ctrl.ngClass, 'ng-class-false': !$ctrl.ngClass }">Dyrektywa ngClass</span> <input type="checkbox" ng-model="$ctrl.ngClass"> </div> <div class="group"> <table class="table table-responsive"> <thead> <td>Lp.</td> <td>First Name</td> <td>Last Name</td> </thead> <tr ng-repeat="user in $ctrl.users" ng-class="{ 'table-even': $even, 'table-odd': $odd }"> <td>{{ $index + 1 }}</td> <td>{{ user.firstName }}</td> <td>{{ user.lastName }}</td> </tr> </table> </div> <div class="group"> <h1>{{ $ctrl.counter }}</h1> <button type="button" class="btn btn-primary" ng-click="$ctrl.click()">Zwiększ o 1</button> <button type="button" class="btn btn-primary" ng-dblclick="$ctrl.dblclick()">Zwiększ o 2</button> </div> <div class="group"> <a ng-href="http://www.adres.pl/{{$ctrl.counter}}">http://www.adres.pl/{{ $ctrl.counter }}</a> </div> <div class="group"> <input data-ng-keydown="$ctrl.clog('keydown')" placeholder="keydown"> <br> <input data-ng-keypress="$ctrl.clog('keypress')" placeholder="keypress"> <br> <input data-ng-keyup="$ctrl.clog('keyup')" placeholder="keyup"> <br> <p>Typing in the input box below updates the keycode</p> <input ng-keyup="event=$event"> <p>event keyCode: {{ event.keyCode }}</p> <p>event altKey: {{ event.altKey }}</p> </div> <div class="group"> <button class="btn btn-default" ng-mousedown="$ctrl.clog('ngMousedown')" ng-mouseenter="$ctrl.clog('ngMouseenter')" ng-mouseleave="$ctrl.clog('ngMouseleave')" , ng-mousemove="$ctrl.clog('ngMousemove')" , ng-mouseover="$ctrl.clog('ngMouseover')" ng-mouseup="$ctrl.clog('ngMouseup')">Mysz</button> </div> <div class="group"> <input type="text" ng-readonly="$ctrl.ngRead"> <input type="checkbox" ng-model="$ctrl.ngRead"> </div> <div class="group"> <p ng-style="$ctrl.ngStyle">Przykładowy tekst</p> </div> <div class="group"> <form data-ng-submit="$ctrl.submit()"> <input type="text" ng-model="$ctrl.submitText" name="text" /> <input type="submit" class="btn btn-default" id="submit" value="Wyślij" /> </form> </div>
Pierwsza omawiana dyrektywa wyświetla napis Dyrektywy za pomocą ng-bind.
Kolejny przykład prezentuje użycie ng-cloak. Przypominam, aby osiągnąć zamierzony efekt, o którym mówiłem na początku wpisu należy dodać klasy css [ng\:cloak], [ng-cloak], .ng-cloak.
ng-bind-html wstrzykuje nam do elementu span kod HTML <strong>Przykładowy kod HTML<strong>.
Następna omawiana dyrektywa w przykładowej aplikacji to ngChange, nasłuchuje zmian na polu input, po wpisaniu każdej litery następuje wyświetlenie obecnego ciągu znaków w konsoli.
ng-class zmienia kolor wyświetlanego tekstu w zależności od zaznaczonego checkboxa.
Kolejną omawianą dyrektywą jest ng-repeat, która wyświetla tabele użytkowników pokazując liczbę porządkową jako $index + 1, a także nadając klasę css w zależności od parzystości $index ($even i $odd).
ng-dblclick to kolejna dyrektywa, która przyjmuje funkcję zwiększającą wyświetlany licznik o 2.
ng-href określa link za pomocą licznika wykorzystanego przy dyrektywie ng-dblclick.
Następne dyrektywy pokazuje sposób obsługi klawiszy. Efekty możemy zobaczyć w konsoli.
Kolejne dyrektywy pokazują sposób obsługi zdarzeń wywołanych przez mysz. Efekty możemy zobaczyć w konsoli.
ng-readonly za pomocą checkboxa ustawia pole input na tylko do odczytu.
ng-style określa kolor elementu p.
Ostatnia już dyrektywa odpowiada za wykonanie niestandardowej operacji po przesłaniu formularza za pomocą przycisku z typem submit. W naszej aplikacji efektem będzie wyświetlenie w konsoli odczytanej wartości z pola tekstowego.
Efekty działania
Podsumowanie
Pisanie aplikacji w AngularJS dzięki wykorzystaniu tych dyrektyw staje się jeszcze bardziej przyjemne. Dają nam wiele możliwości rozbudowy naszych aplikacji takich jak: dynamiczne dodawanie klas lub styli css do elementów, obsługa zdarzeń muszy i klawiatury, a także wiele innych. Warto zaznaczyć, że to nie wszystkie dostępne dyrektywy, a jedynie część. Jeśli chcesz poznać pozostałe zachęcam do zajrzenia w dokumentację omawianego frameworka.