W tym wpisie zajmę się składnią controller as, a także możliwym utworzeniem kontrolera bez użycia usługi $scope przy pomocy tej skladni. Zaprezentuje, aplikację napisaną z wykorzystaniem obu metod, tak aby móc zobaczyć różnice w kodzie pomiędzy kontrolerem wykorzystującym wstrzyknięty obiekt $scope, a kontrolerem wiążącym adekwatności oraz metody za pomoca this.
Controller As w teorii
Od wersji AngularJS 1.2 została udostępniona składnia controller as, jednak przez cały czas w polskim internecie czy książkach mamy przykłady pokazujące działanie omawianego frameworka w oparciu o usługę $scope. Zalecane jest w tej chwili tworzenie aplikacji w oparciu o dziś omawianą metodę, a także na komponentach, które zostaną przedstawione w kolejnym wpisie cyklu.
Projektowanie aplikacji z wykorzystaniem $scope uznane zostało za przestarzałe i choćby przy małych aplikacjach zalecane jest wykorzystywanie konstrukcji controller as. Obiekt $scope wykorzystywany jest jedynie przy usługach jakie oferuje np. $watch(), $emit() czy $on().
Aplikacja kliker
To prosta aplikacja, której zadaniem będzie pokazanie różnic w implementacji obu metod. Jej zadanie to zliczanie liczby kliknięć w przycisk. Zatem będziemy mieć metodę odpowiedzialną za obsługę kliknięcia oraz adekwatność przechowująca ilość kliknięć. Przejdźmy teraz do implementacji z wykorzystaniem obiektu $scope.
Implementacja $scope
<!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 #8</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% } </style> </head> <body ng-controller="appCtrl"> <h1>AngularJS #8</h1> <div> <div> <h1>Clicked {{count}}</h1> <button ng-click="clicked()">Click!</button> </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.controller("appCtrl", ['$scope', appCtrl]); function appCtrl ($scope) { $scope.count = 0; $scope.clicked = function () { $scope.count++; } } </script> </body> </html>W kodzie JS jak zawsze tworzymy moduł naszej aplikacji, a następnie deklarujemy kontroler. Drugim parametrem jest tablica składająca się z dwóch elementów. Pierwszy to obiekt $scope, a drugi to funkcja, której ciało znajduje się poniżej zadeklarowanego kontrolera.
Funkcja ta, odpowiada za całą obsługę utworzonego kontrolera. W parametrze przekazany jest obiekt $scope, któremu przypisana jest adekwatność count z wartością 0. Poza tą adekwatnością przypisana jest również metoda służąca do inkrementacji adekwatności count. Jedną z zalet tego rozwiązania jest większa czytelność kodu zwłaszcza, gdy mamy sytuacje, kiedy w jednym pliku html występuje wiele kontrolerów.
Teraz przechodzimy do pliku index.html, gdzie wprowadzamy nasz kontroler w dyrektywie ng-controller.
<body ng-controller="appCtrl">Do pól z obiektu $scope odwołujemy się dzięki nazw adekwatności jakie nadaliśmy w naszej funkcji.
<h1>Clicked {{count}}</h1> <button ng-click="clicked()">Click!</button>Implementacja controller as
Teraz omówię drugi sposób tworzenia kontrolera bez wykorzystywania obiektu $scope.
<!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 #8</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% } </style> </head> <body ng-controller="appCtrl as app"> <h1>AngularJS #8</h1> <div> <div> <h1>Clicked {{app.count}}</h1> <button ng-click="app.clicked()">Click!</button> </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.controller("appCtrl", appCtrl); function appCtrl () { var ctrl = this; ctrl.count = 0; ctrl.clicked = function () { ctrl.count++; } } </script> </body> </html>Podobnie jak wcześniej tworzymy moduł naszej aplikacji. Następnie przystępujemy do utworzenia kontrolera, jednak tym razem drugim parametrem jest nazwa funkcji, która obsługuje utworzony przez nas kontroler. Na początku tej funkcji deklarujemy zmienną ctrl i przypisujemy jej this, czyli odwołanie do funkcji (funkcja ta jest wywołana podczas tworzenia kontrolera, zatem this odwołuje się do utworzonego kontrolera). Nazwa tej zmiennej pochodzi od słowa controller.
Kolejnym korkiem jest utworzenie wartości count zaliczającej ilość kliknięć. Na koniec tworzymy metodę odpowiedzialną za inkrementacje pola count.
Teraz przejdźmy do pliku z rozszerzeniem .html, tutaj mamy kilka zmian.
<body ng-controller="appCtrl as app">Przy wprowadzeniu kontrolera nie podajemy już samej nazwy, ale dodatkowo wstawiamy słowo najważniejsze as oraz nazwę, przez którą będziemy się odwoływać do niego. Tak jak na przykładzie powyżej.
Kolejną zmianą jest, odwoływanie się do adekwatności i metod. Wynikają one ze sposobu deklaracji kontrolera. Teraz przed podaniem pola czy metody należy wcześniej wstawić nazwę podaną po słowie as w dyrektywie ng-controller.
<h1>Clicked {{app.count}}</h1> <button ng-click="app.clicked()">Click!</button>Efekt działania aplikacji
Podsumowanie
W tym wpisie dowiedzieliśmy się, w jaki inny sposób możemy tworzyć kontrolery. Porównaliśmy różnice w sposobie zapisu na podstawie prostej aplikacji, która liczy kliknięcia w przycisk. Dzięki temu mogliśmy utworzyć kontroler bez wstrzykiwania obiektu $scope. W kolejnym wpisie przedstawię, w jaki sposób tworzy się komponenty w AngularJS, tak abyśmy mogli w kolejnych wpisach pracować na kodzie, który jest rekomendowany.
Jeśli zaciekawił Cie ten wpis i chcesz być na bieżąco z kolejnymi to zachęcam do polubienia mojego fanpage Bugajsky.