Warum AngularJS auch für Java-Entwickler interessant ist

Erste Schritte

Als „Hello World“ der neu aufkommenden JavaScript-MVC-Frameworks wie AngularJS hat sich eine kleine To-do-List-App etabliert (Abbildung 1 und [1]). Eine Angular-Implementierung wollen wir uns hier anhand des Codes in Listing 1 und Listing 2 etwas genauer anschauen. Für das Styling wird Bootstrap [2] verwendet. Der Code ist eine leicht angepasste Variante eines der vielen Beispiele auf der AngularJS-Website [3].

Abb. 1: Todo-List Anwendung mit AngularJS und Bootstrap

Als Erstes binden wir den nötigen JavaScript-Code ein, schön brav, als letzte Elemente im body-Tag (Zeile 15 und 16). Angular wartet, bis das Dokument fertig geladen ist und sucht dann nach dem Attribute ng-app, das in einem beliebigen Tag vorkommen kann, aber nur einmal pro Seite vorkommen sollte. Bei uns steht ng-app im body-Tag in Zeile 1. Angular verarbeitet nur den Teil des DOM, der durch dieses Attribut markiert ist. In diesem Element und allen seinen Kindern sucht Angular nach so genannten Direktiven. Das können Tags, Attribute oder CSS-Klassen sein – mehr dazu später. In unserem Beispiel sorgt das Attribut ng-controller in Zeile 1 dafür, dass für den body und seine Kinder eine Instanz des Controllers, der unter dem Namen TodoCtrl registriert wurde, verwendet wird (Listing 2, Zeile 2). Controller und View kommunizieren über eine Art View-Model, in Angular Scope genannt, der dem Controller übergeben wird und auf dessen Properties von der View aus zugegriffen werden kann.

In Listing 1, Zeile 3 sehen wir zwei One-Way Bindings mittels der Notation {{}}. Im ersten Binding wird die Funktion remaining verwendet, im zweiten die Länge des Array todo abgefragt. todo ist genauso eine vom Controller im Scope definierte Property wie remaining, mit dem Unterschied, dass remaining eine Funktion ist (Listing 2, Zeilen 3 und 12). Da Funktionen in JavaScript Objekte erster Klasse sind, können sie wie Werte und andere Objekte als Referenz übergeben werden. Außerdem können Objekte dynamisch um Properties erweitert werden, wie wir es hier mit dem Scope-Objekt machen. In Listing 1, Zeile 5 wird mittels ng-repeat über alle Einträge in todo iteriert, um für jeden Listeneintrag mit einer Checkbox und einem Text auszugeben. Für jede Iteration legt Angular einen neuen Child Scope an und speichert den aktuellen Eintrag in der von uns definierten Property, hier todo. Da Scopes in AngularJS ausgehend vom Root Scope einen Baum bilden, der über JavaScripts Prototype-Mechanismus abgebildet wird, kann auch immer transparent auf Properties der Parent Scopes zugegriffen werden. In Listing 1, Zeile 10 wird ein Formular definiert, über das sich neue Todo-Einträge erfassen lassen. Das Textfeld ist mittels ng-model an die Property todoText gebunden. Bei ng-model handelt es sich um ein Two-Way Binding. Am Formular selbst wird mit ng-submit definiert, welche Funktion im Scope aufgerufen werden soll, wenn das Formular abgesendet wird. Die Funktion addTodo (Listing 2, Zeile 7), die durch Drücken der Enter-Taste im Textfeld oder durch Klick auf den ADD-Button aufgerufen wird, liest den Wert aus todoText aus und erzeugt damit einen neuen Eintrag im todos-Array. Durch diese Änderung wiederum wird automatisch das UI aktualisiert. Zu beachten ist dabei, dass im gesamten Controller auf kein DOM-Element zugegriffen wird. Der Controller bzw. die Funktionen im Scope kennen die View nicht.

Listing 1
  

Todo

{{remaining()}} of {{todos.length}} remaining
  • {{todo.text}}

Listing 2
angular.module('myModule', [])
.controller("TodoCtrl", function($scope) {
  $scope.todos = [
    {text:'learn angular', done:true},
    {text:'build an angular app', done:false}];

  $scope.addTodo = function() {
    $scope.todos.push({text:$scope.todoText, done:false});
    $scope.todoText = '';
  };

  $scope.remaining = function() {
    var count = $scope.todos.reduce(function(sum, todo) {
      var value = todo.done ? 0 : 1;
      return sum + value;
    }, 0);
    return count;
  };
});
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.