angularjs - podstawy
TRANSCRIPT
Cechy AngularJS
• Framework MVC/MVVM
• Dodatkowe atrybuty HTML
• Modele w postaci POJO (Plain Old Javascript
Object)
• Zestaw komponentów ułatwiających organizację
projektu
• Two-way Data Binding
• Dirty Checking
• Zbudowany z wykorzystaniem jQuery
• Duża popularność i wsparcie społeczności
Komponenty - Modulevar application = angular.module('countriesApp', [ 'ui.router']);
application.config(['$locationProvider', '$stateProvider', '$urlRouterProvider', function($locationProvider, $stateProvider, $urlRouterProvider){
$locationProvider.hashPrefix('');
$stateProvider.state('countryList', { url: "/", templateUrl: "app/view/country-list.html" });
$stateProvider.state('countryView', { url: "/:name", templateUrl: "app/view/country-view.html" });
$urlRouterProvider.otherwise('/');}]);
Komponenty - Module<html data-ng-app="countriesApp">
<head lang="en">
<meta charset="UTF-8">
<title>AKAI Countries</title>
</head>
<body>
<div data-ui-view></div>
</body>
</html>
Komponenty - Controller
• Dostarcza dane widokom ($scope)
• Zawiera logikę widoków
• Nie powinien manipulować drzewem DOM
• Przypisywany widokom przy pomocy atrybutu
HTML ng-controller
Komponenty - Controllerapplication.controller('countryListController', ['$scope', 'countryService', function($scope, countryService){ $scope.countries = []; $scope.loadingCountries = true;
$scope.countryModel = { name: "", symbol: "" };
countryService.getList().then(function(list){ $scope.countries = list; $scope.loadingCountries = false; });
$scope.addCountry = function() { $scope.countries.push($scope.countryModel); $scope.countryModel = { name: "", symbol: "" } }
}]);
Komponenty - View
• Zapisywany w języku HTML rozszerzonym o dodatkowe atrybuty
• Ma dostęp do wszystkich elementów $scope• Dodatkowe atrybuty:
– ng-if– ng-show/ng-hide– ng-click– ng-repeat– ng-model– ng-class– ng-style– ng-src– ng-attr-{{ }}
Komponenty - View
<div data-ng-controller="countryListController"> <data-loader data-is-loading="loadingCountries"> <div> <label for="country-name">Name:</label> <input type="text" data-ng-model="countryModel.name" name="CountryName" id="country-name" /> </div> <div> <label for="country-symbol">Symbol:</label> <input type="text" data-ng-model="countryModel.symbol" name="CountrySymbol" id="country-symbol" /> </div> <div> <button data-ng-click="addCountry()">Add</button> </div> <hr> <div data-ng-repeat="country in countries track by $index"> <span> {{ country.name }} </span> <span> {{ country.symbol | countryCode }} </span> <a data-ui-sref="countryView({ name: country.name })"> view </a> </div> </data-loader></div>
Komponenty - Service
• Oparty o wzorzec projektowy Singleton• Może zostać wstrzyknięty w dowolne miejsce aplikacji przy
pomocy Dependency Injection• Często wykorzystywany do implementacji warstwy pobierającej
dane• Może zostać wykorzystany do implementacji warstwy Modeli• Predefiniowane serwisy:
– $http– $window– $q
Komponenty - Service
application.service('countryService', ['$http', '$q', function ($http, $q) {
this.getList = function () { var deferred = $q.defer();
$http.get('https://restcountries.eu/rest/v1/all').success(function (data) { var result = []; for (var i = 0; i < data.length; i++) { result.push({ name: data[i].name, symbol: data[i].alpha2Code }); } deferred.resolve(result); });
return deferred.promise; };
}]);
Komponenty - Factory
• Działanie i zastosowanie identyczne jak Service• Zwraca wynik funkcji zamiast instancji funkcji
Komponenty - Factory
application.factory('countryFactory', ['$http', '$q', function ($http, $q) { return { getList: function() { var deferred = $q.defer();
$http.get('https://restcountries.eu/rest/v1/all').success(function (data) { var result = []; for (var i = 0; i < data.length; i++) { result.push({ name: data[i].name, symbol: data[i].alpha2Code }); } deferred.resolve(result); });
return deferred.promise;
} };}]);
Komponenty - Directive
• Komponent interfejsu użytkownika przeznaczony do wielokrotnego użytku
• Nie powinien zawierać logiki biznesowej• Może manipulować drzewem DOM• Można do niego przekazać parametry:
– =– @– &
• Często używany do inicjalizacji bibliotek jQuery• Częsty powód wycieków pamięci
Komponenty - Directiveapplication.directive('loader', [ function(){ return { restrict: 'AE', replace: true, transclude: true, templateUrl: 'app/directive/loader/loader.html', scope: { isLoading: '=' }, link: function($scope, element) { var scale = 10; var negative = true;
$scope.animation = setInterval(function(){ angular.element(element).find(".loader").css('transform', 'scale(' + scale/10 + ')'); if(negative) scale -= 1; else scale += 1; if(scale == 0 || scale == 10) negative = !negative; }, 50);
$scope.$on('$destroy', function() { clearInterval($scope.animation); }); } } }]);
Komponenty - Filter
• Pozwala na manipulację danymi wejściowymi• Nie powinien zawierać logiki biznesowej• Domyślnie dostępny w widokach• Pozwala na przetwarzanie strumieniowe przy pomocy operatora |• Predefiniowane filtry:
– orderBy– filter– date– currency
Komponenty - Filter
application.filter('countryCode', function() {
return function(input) {
return '[' + input + ']'
};
});
Zagrożenia i Problemy
• Nauka AngularJS nie jest prosta• Skalowalność i wydajność aplikacji• Czytelność struktury projektu• Wycieki pamięci• Ograniczone narzędzia do pisania testów (Protractor)• Pokusa używania jQuery• SEO• AngularJS 2.0
Biblioteki
• ui-router• angular-bootstrap/angular-foundation• angular-ui• angular-translate• ngResource