DyrektywyCzęść NR.5Czego nauczyliśmy się do tej pory?

Wiemy, że jeśli chcemy, aby jakieś dane pojawiły się na stronie, musimy użyć parametru $scope.

Do parametru $scope umieszczamy nasz model.



<script>
var MainController = function ($scope) {

    $scope.mytext = "Angular JS Rulez";

}
</script>

Model nie dotyka HTML.

Wiemy jak możemy wyświetlić nasz model na stronie HTML bez określania układu elementów w kontrolerze. Nie wiemy nic na temat widoku HTML, z którego korzystamy na stronie.

Kontroler i model nie są bezpośrednio powiązane z widokiem. Nie muszę się martwić choćby o to, w jakiej przeglądarce będą te elementy wyświetlane.

<body>
    <div ng-app>
        <div ng-controller="MainController">
            <p>{{mytext}}</p>
        </div>
    </div>
</body>

W widoku używają specjalnych wyrażeń (“binding expressions”).

Wyrażenie “{{ }}” zwany inaczej ngBind jest jedną z dyrektyw Angular. Jej celem jest wiązanie danych.

Ta dyrektywa może sięgnąć do modelu by wyświetlić odpowiednie dane w odpowiednim miejscu na ekranie.

Proces zarządzania prezentacją danych nie zachodzi z procesem ich pobierania.W ten sposób możemy nie tylko pokazać tekst, ale także pokazać obrazki.

Jak na razie koncentrowaliśmy się na pobraniu danych. Widok obecnie tylko prezentuje dane.Co jednak, jeśli musimy przesłać informację z widoku do modelu.

Przykładem może być formularz HTML.

<form>
    Add new game:
    <input name="gameName" type="text"/>
    <input type="submit" value="Add"/>
</form>

Najpierw mamy pole tekstowe, w którym musimy podać wartość tekstową.

Wartość tą musimy z powrotem przesłać do modelu.

Druga sprawa gdy użytkownik zatwierdzi ten formularz klikając przycisk “Add”. Muszę jakoś odpowiedzieć na to wydarzenie i wysłać coś do serwera, tak aby operacja dodania nowego elementu rzeczywiście zadziałała

Na pomoc przychodzą dyrektywy.

Dyrektywa polega na tym, aby w samym widoku określić współpracę z modelem.

Wiemy, że mamy dyrektywę by przesłać dane z modelu do widoku. Istnieją też dyrektywy, które potrafią przesłać informację z widoku do modelu.

Istnieją też dyrektywy, które działają w obu kierunkach.

Nauczmy się więc nowych dyrektyw.

ng-model

Wróćmy do istniejącego kodu.

Wyświetlam obecnie konto GitHub “PanNiebieski”.

Chcę jednak stworzyć pole tekstowe, po którym będę mógł wyszukiwać innych użytkowników.

<div ng-app="KursAngular">
    <div ng-controller="MainController">
        <div>
            <form name="searchInGitHub">
                <input type="search" placeholder="Nazwa"/>
                <input type="submit" value="Szukaj"/>
            </form>
        </div>
        <div>
            <p>{{error}}</p>
        </div>
        <p>Imie i nazwisko :{{user.name}}</p>
        <p>Email : {{user.email}}</p>
        <p>Adress Bloga : {{user.blog}}</p>
        <p>Utworzony : {{user.created_at}}</p>
        <p>Awatar : </p>
        <p>
            <img ng-src="{{user.avatar_url}}" 
            title="{{user.name}}" />
        </p>
    </div>
</div>

Dodałem więc do kodu następujący formularz, który umożliwi wyszukiwanie.

Skoro chcemy wyszukiwać użytkowników, musimy jakoś przekazać informację na temat tego, co chcemy szukać.

<div>
    <form name="searchInGitHub">
        <input type="search" placeholder="Nazwa"/>
        <input type="submit" value="Szukaj"/>
    </form>
</div>

Do pola tekstowego dodałem dyrektywę “ng-model”. Dodała ona właściwość do obecnego kontrolera. Do tej właściwości mogą się odwołać i w kontrolerze, i w widoku.

Dyrektywang-model wiąże też zawartość pola tekstowego z tą dodatkową właściwością, która pojawiła się w kontrolerze.

Relacja jest dwukierunkowa. Oznacza to, że jeśli zmienię zawartość pola tekstowego to zmienię zawartość username. Jeśli zmienię wartość username, zmienię także wartość tego pola tekstowego.

<div>
    <p>{{ username }}</p>
    <form name="searchInGitHub">
        <input type="search" placeholder="Nazwa" 
        ng-model="username"/>
        <input type="submit" value="Szukaj"/>
    </form>
</div>

Jak sprawdzić, czy to działa w praktyce. Wyżej skorzystałem z prostej dyrektywy, która ma wyświetlić zawartość właściwości “username”.

Tak jak mówiłem wiązanie jest dwustronne.

Wewnątrz kontrolera mogę ustawić domyślną wartość pola tekstowego. W tym wypadku jest to “PanNiebieski”.

ng-model

Dodaj ten zapis do swojego kontrolera i zobacz rezultat w praktyce.

var MainController = function ($scope, $http) {

    $scope.username = "PanNiebieski"

Wiemy jak manipulować zawartością pola tekstowego.

Jak jednak przypisać zdarzenie kliknięcia do przycisku.

Oczywiście kolejną dyrektywą.

ng-click

Dyrektywa ng-click jest bardzo prosta.

Do przycisku dodaję tę dyrektywę, a wewnątrz niej definiuję nazwę funkcji oraz parametry jakie chcę przekazać do tej funkcji.

W tym wypadku funkcja nazywa się “search”, będzie ona potrzebować jeden parametr “username”. Wartość tego parametru jest automatycznie przekazywana w wyniku działania dyrektywy ng-model.

<div>
    <p>{{ username }}</p>
    <form name="searchInGitHub">
        <input type="search" placeholder="Nazwa" 
        ng-model="username"/>
        <input type="submit" value="Szukaj" 
        ng-click="search(username)"/>
    </form>
</div>

Do kontrolera wewnątrz jego nawiasów klamrowych musimy zdefiniować tę funkcję.

Funkcja ta wywoła zapytanie HTTP do usługi GitHub, a ona zwróci odpowiedniego użytkownika.

$scope.search = function (username) {
    $http.get("https://api.github.com/users/" + username).
    then(onRequestCompleted, onError);
}

Zobaczmy jak teraz działa nasza aplikacja w praktyce.

ng-click

Wybrałem przypadkowe nazwy i trochę mnie przeraziło, że są nazwy konta określone pojedynczymi imionami. Na tym animowanym obrazku powyżej ciężko to zauważyć, ale z każdym naciśnięciem przycisku funkcja kontrolera wywołuje się ponownie.

Oznacza to, że lepiej z kontrolera usunąć pierwsze zapytania do użytkownika o nazwie PanNiebieski.

(function () {
    var app = angular.module("Kurs", []);

    var MainController = function ($scope, $http) {

        $scope.username = "PanNiebieski"

        var onRequestCompleted = function (response) {
            $scope.user = response.data;
        }

        var onError = function (reason) {
            $scope.error = "Nie można pobrać informacji"
        }

        $scope.search = function (username) {
            $http.get("https://api.github.com/users/" + username).
            then(onRequestCompleted, onError);
        }

    }

    app.controller("MainController", ["$scope", "$http", MainController]);

})();

Dyrektyw jest oczywiście więcej, ale o tym w następnym wpisie.