AngularJS
Podstawy
Wojciech Panek - Tech Lead, Apptension
www.apptension.com
https://bitbucket.org/WojtekPanek/akaicountries
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
Komponenty - Module
• Pozwala na grupowanie
• Zarządzanie Dependency Injection
• Konfiguracja
Komponenty - Module
var 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 - Controller
application.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 - Directive
application.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
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
Biblioteki
• ui-router
• angular-bootstrap/angular-foundation
• angular-ui
• angular-translate
• ngResource
Narzędzia
Dziękuję za uwagę

AngularJS - podstawy

  • 1.
    AngularJS Podstawy Wojciech Panek -Tech Lead, Apptension www.apptension.com
  • 2.
  • 3.
    Cechy AngularJS • FrameworkMVC/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
  • 4.
  • 5.
    Komponenty - Module •Pozwala na grupowanie • Zarządzanie Dependency Injection • Konfiguracja
  • 6.
    Komponenty - Module varapplication = 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('/'); }]);
  • 7.
    Komponenty - Module <htmldata-ng-app="countriesApp"> <head lang="en"> <meta charset="UTF-8"> <title>AKAI Countries</title> </head> <body> <div data-ui-view></div> </body> </html>
  • 8.
    Komponenty - Controller •Dostarcza dane widokom ($scope) • Zawiera logikę widoków • Nie powinien manipulować drzewem DOM • Przypisywany widokom przy pomocy atrybutu HTML ng-controller
  • 9.
    Komponenty - Controller application.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: "" } } }]);
  • 10.
    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-{{ }}
  • 11.
    Komponenty - View <divdata-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>
  • 12.
    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
  • 13.
    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; }; }]);
  • 14.
    Komponenty - Factory •Działanie i zastosowanie identyczne jak Service • Zwraca wynik funkcji zamiast instancji funkcji
  • 15.
    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; } }; }]);
  • 16.
    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
  • 17.
    Komponenty - Directive application.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); }); } } } ]);
  • 18.
    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
  • 19.
    Komponenty - Filter application.filter('countryCode',function() { return function(input) { return '[' + input + ']' }; });
  • 20.
  • 21.
    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
  • 22.
  • 23.
    Biblioteki • ui-router • angular-bootstrap/angular-foundation •angular-ui • angular-translate • ngResource
  • 24.
  • 25.