Check All Checkboxen mit AngularJS

Wieder einmal komme ich von einer Angular.JS Schulung nach Hause. Wieder einmal hatten die Teilnehmer des Trainings durchaus Probleme die Konzepte von Angular mit ihren bestehenden Skills zu verbinden. Konkret ging es um den Anwendungsfall eine Liste von HTML Checkboxen mit einem Klick zu aktivieren. Bei der Rückreise vom Angular Kurs mit der Bahn, hat man Zeit darüber nachzudenken und das Ergebnis ist nicht was man erwarten würde.

Kennen Sie den? Wer einen Hammer besitzt, für den ist das Leben voller Nägel. Kann man so interpretieren, das man das tut was man kann. In einer Angular Single Page Application ist das ein HTML View und ein Viewmodel Scope per JavaScript Controller. Dieser stellt die Methoden bereit um aus dem View Änderungen am Scope bla bla bla.

Schon sind wir in ein kleines Buzz Word Bingo mit Angular eingestiegen. Also lassen sie uns einen Schritt zurück treten. Worum geht es eigentlich in einer Web Site? Das völlig konstruierte Beispiel hat folgende Benutzer Anforderungen.

  • Eine Liste Namen anzeigen
  • max 2 Namen einzeln auswählen
  • die ausgewählten Namen zählen und anzeigen
  • Alle Namen aus oder abwählen können

Mancher JavaScript Developer fängt nun an Tests zu schreiben, andere einen Controller. Ich bin der visuelle Typ und zeichne das UI zuerst.

image

Der dazu notwendige Angular.JS Controller

   1:   angular.module('App', [])
   2:          .controller('myController', function ($scope) {
   3:              $scope.liste = [{ wert: "hannes", checked: false },
   4:                  { wert: "maria", checked: true },
   5:                  { wert: "franz", checked: false },
   6:                  { wert: "Hias", checked: false }];
   7:          });

 

Nun könnte man in den Controller einen Watcher einbauen, der die Liste überwacht und bei Änderung einen Zähler anwirft. Der Wert wird dann einer Scope Variablen zugewiesen. Noch wach?

Warum muss sich eine User Interface Geschichte im Controller abspielen? Wo steht das geschrieben?

Angular ist relativ mächtig, wenn es um Datenbindung per Expressions geht. Ausgehend von der Liste der Namen wird mit einem Filter Ausdruck nur die ausgewählten selektiert. Einmal Klammer außen rum und mit lengt die Anzahl ausgeben.

   1:  gesamt {{(liste | filter:{'checked':true}).length }} 

 

Das Ergebnis sieht man am obigen Bild. Well die Grundidee durchaus bestechend ist, wird das gleiche Konzept verwendet um bei mehr als einem ausgewählten Namen die übrigen zu deaktivieren. So kann der Benutzer maximal zwei Namen auswählen, aber die gewählten auch wieder deaktivieren.

   1:  <x ng-repeat="mensch in liste">
   2:     <input type="checkbox" name="test" class="chklist"
   3:         ng-model="mensch.checked"  
   4:         ng-disabled="mensch.checked==false && 
(liste | filter:{'checked':true}).length>1"
   5:     />{{mensch.wert}}
   6:  </x>

Auch das kann man im Screenshot oben erkennen, hannes und hias sind graue Boxen.

Ausgerüstet mit der Erkenntnis, das nicht alles Angular Code Behind sein muss, nun die letzte Aufgabe. Wie kann man alle Checkbocen anhaken oder eben nicht. Wenn man im UI bleibt, ist JQuery das beste Tool um  DOM Manipulationen vorzunehmen. Dafür gibt es verschiedene Selektoren, über ID oder Typ oder eben CSS Klassen, hier chklist genannt.

   1:<input type="checkbox" onclick=" $('.chklist').prop('checked', this.checked)" />Alle<br />

 

Cool oder? Alternative Lösungen die im Web diskutiert (oder gebloggt ) werden kommen auf ein vielfaches an Code.

Eine kleine Randnotiz. JavaScript’s fähigkeiten Objekte zu jeder Zeit zu erzeugen wird mit Angular.js noch magischer. Obiges Beispiel funktioniert auch ohne die checked Eigenschaft der Liste.

   1:   $scope.liste = [{ wert: "hannes" },
   2:                  { wert: "maria" },
   3:                  { wert: "franz" },
   4:                  { wert: "Hias"}];
Kommentare sind geschlossen