Einführung in AngularJS
-
Upload
sebastian-springer -
Category
Technology
-
view
1.774 -
download
1
Transcript of Einführung in AngularJS
Sebastian Springer@basti_springer
Wednesday, June 26, 13
WER BIN ICH?
• Sebastian Springer
• https://github.com/sspringer82
• @basti_springer
• Teamlead @ Mayflower
Wednesday, June 26, 13
INHALT
• Bootstrap
• Scope
• Controller
• Model
• View
• Direktiven
• Filter
• Dependency Injection
• Module
• Testing
Wednesday, June 26, 13
ANGULAR?
• Open Source MVC Framework
• von Google
• sehr gut erweiterbar
• jQuery lite bundled
• ng-* Direktiven
Wednesday, June 26, 13
INDEX.HTML
Wednesday, June 26, 13
BOOTSTRAP
<!DOCTYPE html><html ng-app> <head> <title>Movie Database</title> <script src="/js/lib/angular.js"></script> </head> <body> Hello {{ 'World!' }} </body></html>
Wednesday, June 26, 13
BOOTSTRAP
Wednesday, June 26, 13
Wednesday, June 26, 13
CONTROLLER
• Funktionen
• Kontrolliert das Verhalten der Applikation
• Verbindet Models und Views
• Scope als Verbindungselement
Wednesday, June 26, 13
INDEX.HTML
Wednesday, June 26, 13
CONTROLLER<!DOCTYPE html><html data-ng-app> <head> <title>Movie Database</title> <script src="/js/lib/angular.js"></script> <script src="/js/controllers.js"></script> </head> <body ng-controller="MovieListCtrl">
{{ name }}
</body></html>
Wednesday, June 26, 13
CONTROLLER<!DOCTYPE html><html data-ng-app> <head> <title>Movie Database</title> <script src="/js/lib/angular.js"></script> <script src="/js/controllers.js"></script> </head> <body ng-controller="MovieListCtrl">
{{ name }}
</body></html>
Wednesday, June 26, 13
JS/CONTROLLERS.JS
Wednesday, June 26, 13
CONTROLLER
function MovieListCtrl($scope) {
$scope.name = 'Matrix';
}
Wednesday, June 26, 13
SCOPE
• Änderungen in Models erkennen
• Ausführungskontext
• An Controller gebunden
Wednesday, June 26, 13
function MovieListCtrl($scope) {
$scope.name = 'Matrix';
}
SCOPE
Wednesday, June 26, 13
<!DOCTYPE html><html data-ng-app> <head> <title>Movie Database</title> <script src="/js/lib/angular.js"></script> <script src="/js/controllers.js"></script> </head> <body ng-controller="MovieListCtrl">
{{ name }}
</body></html>
SCOPE
Wednesday, June 26, 13
Wednesday, June 26, 13
DATA-BINDING
• Das Model hält die Daten
• Die View erhält die Daten und stellt sie dar
• Scope als Verbindungsstück
Wednesday, June 26, 13
TWO-WAY-DATA-BINDING
• Controller gibt den Wert für das Model vor
• Über das Model kann der Wert geändert werden
Wednesday, June 26, 13
TWO-WAY-DATA-BINDINGfunction LoginCtrl($scope) {
$scope.username = 'stranger';
$scope.login = function () { if ($scope.username === 'admin' && $scope.password === 'test') { $scope.user = 'Administrator'; } }
}
Wednesday, June 26, 13
Wednesday, June 26, 13
MODEL
Wednesday, June 26, 13
MODEL
• Daten zur Darstellung in der View
• keinerlei Vorgaben hinsichtlich des Aufbaus
Wednesday, June 26, 13
MODEL
Wednesday, June 26, 13
MODEL
function MovieListCtrl($scope) {
$scope.name = 'Matrix';
}
Wednesday, June 26, 13
VIEW
Wednesday, June 26, 13
VIEW
• Darstellung der Modeldaten
• Zeigt Änderungen des Models sofort an
• Zugriff auf den Scope über {{ }}
Wednesday, June 26, 13
VIEW
Wednesday, June 26, 13
VIEW<!DOCTYPE html><html data-ng-app> <head> <title>Movie Database</title> <script src="/js/lib/angular.js"></script> <script src="/js/controllers.js"></script> </head> <body ng-controller="MovieListCtrl">
{{ name }}
</body></html>
Wednesday, June 26, 13
DIREKTIVEN
Wednesday, June 26, 13
DIREKTIVEN
• HTML Attribute
• Verhalten oder DOM Transformation
• Built-ins und eingene Direktiven
• Eigene Direktiven
• z.B. ngApp, ngController, ngRepeat
Wednesday, June 26, 13
DIREKTIVEN
Wednesday, June 26, 13
JS/CONTROLLERS.JS
Wednesday, June 26, 13
DIREKTIVEN
function MovieListCtrl($scope) {
$scope.films = [ {name: 'Matrix', year: 2005, genre: 'Sci-Fi'}, {name: 'Avatar', year: 2009, genre: 'Sci-Fi'}, {name: 'Gran Torino', year: 2008, genre: 'Drama'} ];}
Wednesday, June 26, 13
INDEX.HTML
Wednesday, June 26, 13
<table> <thead> <tr> <th>Name</th><th>Jahr</th><th>Genre</th> </tr> </thead>
<tbody>
<tr ng-repeat="film in films"> <td>{{film.name}}</td> <td>{{film.year}}</td> <td>{{film.genre}}</td> </tr>
</tbody></table>
Wednesday, June 26, 13
Wednesday, June 26, 13
FILTER
Wednesday, June 26, 13
• Datentransformation
• Verbindung über das Pipe-Symbol
• Eigene Filter
• z.B. uppercase, json
FILTER
Wednesday, June 26, 13
{{ 'Hello World' | uppercase }}
<input ng-model="search">
<table> <thead> <tr> <th>Name</th><th>Jahr</th><th>Genre</th> </tr> </thead>
<tbody> <tr ng-repeat="film in films | filter: search"> <td>{{film.name}}</td> <td>{{film.year}}</td> <td>{{film.genre}}</td> </tr> </tbody></table>
Wednesday, June 26, 13
{{ 'Hello World' | uppercase }}
<input ng-model="search">
<table> <thead> <tr> <th>Name</th><th>Jahr</th><th>Genre</th> </tr> </thead>
<tbody> <tr ng-repeat="film in films | filter: search"> <td>{{film.name}}</td> <td>{{film.year}}</td> <td>{{film.genre}}</td> </tr> </tbody></table>
Wednesday, June 26, 13
Wednesday, June 26, 13
DEPENDENCY INJECTION
Wednesday, June 26, 13
DEPENDENCY INJECTION
• Strukturierung - Komponenten für Model, View, Controller
• Lose Kopplung - DI löst Abhängigkeiten auf
• DI stellt Services zur Verfügung
• Caching Mechanismus
Wednesday, June 26, 13
DEPENDENCY INJECTION
Wednesday, June 26, 13
DEPENDENCY INJECTION
function MovieListCtrl($scope, $http) {
$http.get('/movies').success(function(data) { $scope.films = data; });
}
Wednesday, June 26, 13
DEPENDENCY INJECTION
function MovieListCtrl($scope, $http) {
$http.get('/movies').success(function(data) { $scope.films = data; });
}
Wednesday, June 26, 13
MODULE
Wednesday, June 26, 13
• Geben den Bootstrap-Prozess einer Applikation vor
• Service Modul
• Directive Modul
• Filter Modul
• Application Modul
MODULE
Wednesday, June 26, 13
MODULEvar myApp = angular.module('myApp', []);
myApp.controller('MovieListCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('/movies').success(function(data) { $scope.films = data; });
}]);
Wednesday, June 26, 13
MODULEvar myApp = angular.module('myApp', []);
myApp.controller('MovieListCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('/movies').success(function(data) { $scope.films = data; });
}]);
Wednesday, June 26, 13
TESTING
Wednesday, June 26, 13
TESTS
• Karma als Testrunner
• sudo npm install -g karma
• Angular setzt auf Jasmine
• Zwei Arten von Tests
• Unittests
• E2E-Tests
Wednesday, June 26, 13
UNITTESTS
Wednesday, June 26, 13
UNITTESTS
• Testen Units of Code
• Grundlage für TDD
• Pfad: test/unit/*
• Konfiguration: config/karma.conf.js
Wednesday, June 26, 13
TEST/UNIT/CONTROLLERSPEC.JS
Wednesday, June 26, 13
describe('movieListCtrl', function(){
var scope, ctrl, $httpBackend;
beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) { $httpBackend = _$httpBackend_; $httpBackend.expectGET('data/movies.json').respond( [{"name": "Matrix", "year": 2005, "genre": "Sci-Fi"}] ); scope = $rootScope.$new(); ctrl = $controller(movieListCtrl, {$scope: scope}); }));
Wednesday, June 26, 13
it ("should fetch a list with one movie", function () { expect(scope.films).toBeUndefined();
$httpBackend.flush();
expect(scope.films).toEqual( [{"name": "Matrix", "year": 2005, "genre": "Sci-Fi"}] ); });
Wednesday, June 26, 13
UNITTESTS
$ ./scripts/test.sh
Starting Karma Server (http://karma-runner.github.io)-------------------------------------------------------------------INFO [karma]: Karma server started at http://localhost:9876/INFO [launcher]: Starting browser ChromeINFO [launcher]: Starting browser FirefoxINFO [Firefox 21.0 (Mac)]: Connected on socket id 8lw9q3ZBbNpAb7rc3RpSINFO [Chrome 27.0 (Mac)]: Connected on socket id KI5wy1rfgkIU32cP3RpRFirefox 21.0 (Mac): Executed 4 of 4 SUCCESS (0.134 secs / 0.037 secs)Chrome 27.0 (Mac): Executed 4 of 4 SUCCESS (0.157 secs / 0.044 secs)TOTAL: 8 SUCCESS
Wednesday, June 26, 13
UNITTESTS
Wednesday, June 26, 13
UNITTESTS
INFO [watcher]: Changed file "/srv/angularMovieDB/app/js/controllers.js".
Watcher
Wednesday, June 26, 13
E2E
Wednesday, June 26, 13
E2E
• Testen zusammenhängende Units
• DOM-Manipulationen
• Pfad: test/e2e
• Konfiguration: config/karma-e2e.conf.js
Wednesday, June 26, 13
TEST/E2E/SCENARIOS.JS
Wednesday, June 26, 13
E2E
describe('Movie List', function() {
beforeEach(function() { browser().navigateTo('../../app/index.html'); });
it('should display 3 movies', function() { expect(repeater('table tbody tr').count()).toBe(3); });});
Wednesday, June 26, 13
E2E
• Webserver ausführen
•./scripts/web-server.js
• Tests ausführen
•./scripts/e2e-test.sh
Wednesday, June 26, 13
E2E
./scripts/e2e-test.sh
Starting Karma Server (http://karma-runner.github.io)-------------------------------------------------------------------[2013-06-22 10:26:07.404] [WARN] config - "/" is proxied, you should probably change urlRoot to avoid conflictsINFO [karma]: Karma server started at http://localhost:9876/INFO [launcher]: Starting browser ChromeINFO [Chrome 27.0 (Mac)]: Connected on socket id 4YaYP4NBBNKlOgDS_YbAChrome 27.0 (Mac): Executed 1 of 1 SUCCESS (0.385 secs / 0.189 secs)
Wednesday, June 26, 13
E2E
• http://docs.angularjs.org/guide/dev_guide.e2e-testing
Wednesday, June 26, 13
ANGULAR-SEED
Wednesday, June 26, 13
ANGULAR-SEED
• Basisstruktur für Projekte
• https://github.com/angular/angular-seed
Wednesday, June 26, 13
TIPPS & TRICKS
• Setzt Module ein
• Nutzt den Router
• Achtet auf den Scope
• Nutzt die Direktiven
• Schreibt Tests
Wednesday, June 26, 13
FRAGEN?
Wednesday, June 26, 13
KONTAKT
Sebastian [email protected]
Mayflower GmbHMannhardtstr. 680538 MünchenDeutschland
@basti_springer
https://github.com/sspringer82
Wednesday, June 26, 13