Einführung in AngularJS

Post on 14-May-2015

1.770 views 1 download

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 Springersebastian.springer@mayflower.de

Mayflower GmbHMannhardtstr. 680538 MünchenDeutschland

@basti_springer

https://github.com/sspringer82

Wednesday, June 26, 13