Post on 10-Jul-2015
description
AngularJs4Developers 12 kwietnia 2013
AngularJs4Developers 12 kwietnia 2013
Kim jestem?● Marcin Wosinek● 5 lat doświadczenia w IT
- WebDev: Javascript- C# dev: UnitTests
● Aktualnie js kontraktor w Poznaniu
Wy?
Temat
Nowa rzeczywistość
Tradycyjna architektura stron
Serwer
KLIENT
html z danymi request
Podejście aplikacyjne
Serwer
KLIENT
js template restdane
Komunikacja z backendem{ "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": 10021 }}
Zmiany
Wyzwania - testowalnośćfunction PasswordCtrl() { var msg = $('.ex1 span'); var input = $('.ex1 input'); var strength; this.grade = function() { msg.removeClass(strength); var pwd = input.val(); password.text(pwd); if (pwd.length > 8) { strength = 'strong'; } else { strength = 'weak'; } msg .addClass(strength) .text(strength);
Wyzwania - boilerplate
initialize: function () { this.allCheckbox = this.$('#toggle-all')[0]; this.$input = this.$('#new-todo'); this.$footer = this.$('#footer'); this.$main = this.$('#main');
this.listenTo(app.Todos ,'add',this.addOne); this.listenTo(app.Todos, 'reset', this.addAll); this.listenTo(app.Todos, 'change:completed', this.filterOne); this.listenTo(app.Todos, 'filter', this.filterAll); this.listenTo(app.Todos, 'all', this.render);
app.Todos.fetch();}
AngularJs
Architektura MV*
ViewModel
View Model
Generowane przez serwisy
$scope
Angularowy html
AngularJs core
Kontroler
Widok<ul> <li ng-repeat="todo in todos"> <span></span> </li></ul>
<form ng-submit="addTodo()"> <input ng-model="todoText" /> <input type="submit" value="add" /></form>
Filtry<ul> <li ng-repeat="project in projects | filter:search | orderBy:'name'"> <a href=""></a>: </li></ul>
Kontrolery
$scopeprezentacja
Proste obiekty js// Backboneapp.Todo = Backbone.Model.extend({ defaults: { title: '', completed: false }});
// EmberTodos.Todo = DS.Model.extend({ title: DS.attr('string'), isCompleted: DS.attr('boolean') });
// Angulartodos.push({ title: $scope.newTodo, completed: false });
Two ways binding
Wsparcie dla formularzaprezentacja<!-- Html updated by angular --><form name="exampleForm" class="ng-pristine ng-invalid ng-invalid-required">
Required field: <input ng-model="required" required="" class="ng-pristine ng-invalid ng-invalid-required"></label> <br>
Email field: <input ng-model="email" type="email" class="ng-pristine ng-valid ng-valid-email"></label> <br>
<button ng-disabled="!exampleForm.$valid" disabled="disabled">Submit</button></form>
Wstrzykiwanie zależnościfunction HelloCtrl($scope, $window, $log) { $scope.message = 'Display me in view'; $window.alert('Use window via $window service - that improves testability'); $log.log('We can even test console log calls - thats to $log wrapper');}
Serwisy// Services that persists and retrieves ToDos from// localStoragetodomvc.factory('todoStorage', function () { var STORAGE_ID = 'todos-angularjs';
return { get: function () { return JSON .parse(localStorage.getItem(STORAGE_ID) || '[]'); },
put: function (todos) { localStorage .setItem(STORAGE_ID, JSON.stringify(todos)); }};});
Ścieżki - $routeProviderangular.module('phonecat', []) .config(['$routeProvider', function($routeProvider, $locationProvider) { // $locationProvider.html5Mode(true); $routeProvider .when('/phones', { templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl }) .when('/phones/:phoneId', { templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl }) .otherwise({ redirectTo: '/phones' });}]);
Komunikacja z backendem - $resourcemyApp.factory('ProductService', function($resource) { var ProductResource = $resource('/product/:productId')
, ProductService = {};
ProductService.getItem = function (index) { return ProductResource.get({productId: index});}
ProductService.addItem = function (item) { ProductResource.save({}, item));}
return ProductService;
});
function ProductCtrl($scope, ProductService) { // Take products form ProductService and put it on $scope}
Directives<ANY class="ng-show: {expression};"><ANY ng-show="{expression}"><ANY class="ng-hide: {expression};"><ANY ng-hide="{expression}">
<ng-view> <any ng-view>
<ANY ng-class="{expression}"> <ANY class="ng-class: {expression};">
<ANY ng-switch="expression"> <ANY ng-switch-when="matchValue1">...</ANY> <ANY ng-switch-when="matchValue2">...</ANY> ... <ANY ng-switch-default>...</ANY></ANY>
Yeoman
Karma (Testacular)
Nawyki
Pisanie callbacków
Nawyki
bindowanie
Nawyki
Zmienianie DOM w kontrolerze
Gotchas - pisanie directivesangular.module('blink', []) .directive('blink', function() { return { restrict: 'E', link: function(scope, elm, attr) { setInterval(function() { elm.toggle(); }, parseInt(attr.interval, 10) || 1000); } }; });
Gotchas - ng-model w ng-repeat
// Gotcha!<ul> <li ng-repeat="item in list"> <input ng-model="item" /> </li></ul>
// Work as expected<ul> <li ng-repeat="item in list"> <input ng-model="item.name" /> </li></ul>
Gotchas - minimalizowanie kodusyngularApp.controller('ProductCtrl', function($scope,
ProductApi) {
// easy but minification unfriendly
});
syngularApp.controller('ProductCtrl', ['$scope',
'ProductApi', function($scope, ProductApi) {
// minification resistant
}]);
Gotchas -
$resource
Gotchas - filtry działające tylko na tablicach
filterorderBy
Gotchas -
e2e?
Gotchas - aktualizowanie scope spoza frameworka
$digest$apply
Gotchas - $ w nazwach serwisów
$
Pytania
?
Materiały
● http://angularjs.org/● http://egghead.io/● http://www.youtube.com/user/angularjs
Podsumowanie
Kontakt
● marcin.wosinek@gmail.com● @MarcinWosinek● linki + notatki:http://bit.ly/4Devs-AngularJs
Podziękowania● zdjęcie z publicznością: http://www.flickr.com/photos/dougbelshaw/5604047370/in/photostream● logo BackboneJs: https://github.com/documentcloud/backbone/blob/master/docs/images/backbone.● Two ways binding: http://docs.angularjs.org/guide/dev_guide.templates.databinding● http://karma-runner.github.io/0.8/index.html● http://yeoman.io/