Forms over Data mit Knockout.js. Tilman Börner

Чтение книги онлайн.

Читать онлайн книгу Forms over Data mit Knockout.js - Tilman Börner страница 3

Forms over Data mit Knockout.js - Tilman Börner

Скачать книгу

      Die letzte Zeile zeigt den Dateninhalt des ViewModels an.

      Tipp 3: Fehlermeldungen von Knockout.js

      Knockout.js schreit dann um Hilfe, wenn es ein Binding im HTML-Code findet, zu dem es keine Observable gibt. Umgekehrt gibt es keine Fehlermeldung: Definieren Sie eine Observable im JavaScript-Code, zu der es kein Binding-Element im HTML-Code gibt, meckert Knockout.js nicht.

      Auslösen des Bindings bei jedem Tastendruck

      Das Übertragen des Wertes im input-Element in ko.observable() passiert in der Regel nur, wenn das Feld den Fokus verliert oder die Return-Taste gedrückt wird. Das bedeutet aber, dass solche Funktionen wie Autovervollständigung oder Suchen während der Eingabe nicht implementiert werden könnten. Aber auch dafür hat Knockout.js eine Lösung parat.

      Wer so etwas implementieren will, muss dem Binding noch einen Konfigurationsparameter mitgeben, der festlegt, wann der Abgleich zwischen View und ViewModel passieren soll. Im Fall des value-Attributs des input-Elements ist das der Parameter valueUpdate: 'afterkeydown' oder vollständig:

      <input type="text" data-bind="value: name,

      valueUpdate: 'afterkeydown'" />

      Bei Verwendung von Tipp 2 sehen Sie, dass sich der Inhalt des ko.observable()-Feldes name bei jedem Tastendruck ändert.

      Berechnete Felder: ko.computed

      Gertrud überlegt es sich noch mal anders: Sie hätte gern sowohl Vor- als auch Nachname auf dem Bildschirm. Hintereinander. Das lässt sich sehr einfach mit einer berechneten Observable erreichen. Dazu definiert man ein neues Feld

      totalName = ko.computed(function(){

      return this.firstname + " " + this.lastname; });

      Abbildung 3: Berechnete Felder können beispielsweise die Länge von Wörtern anzeigen.

      totalName wird dann an die data-bind-text-Eigenschaft des div-Elements gebunden. Jedes Mal, wenn sich jetzt einer der beiden Namen Vorname oder Nachname verändert, berechnet Knockout.js den Wert neu und weist ihn dem Element in der View zu. Dieser Mechanismus eignet sich beispielsweise auch, um Konvertierungen zwischen verschiedenen Währungen oder Zeiten vorzunehmen.

      throttle verzögert die Auslösung

      Sofern der Event-Handler, der bei jedem Tastendruck ausgelöst wird, nur auf dem Client läuft, also nicht auf einen Server zugreifen muss, passiert das in zufriedenstellender Geschwindigkeit. Was aber, wenn für den eingegebenen Wert vom Server Daten geholt werden müssen? Dann würde bei jedem Tastendruck eine Anfrage über Ajax an den Server abgeschickt werden. Dieser Roundtrip, bis die Daten beim Client angelangt und verarbeitet sind, kann je nach Bandbreite und Geschwindigkeit des Servers dauern, was beim Eintippen eines Suchbegriffs nervtötend ist.

      Für so ein Szenario bietet Knockout.js die Methode throttle an: Drosselung. Damit ist es möglich, das Setzen einer berechneten Observable zu verzögern. Beispiel: myval ist als ko.observable() an das value-Attribut des Eingabefelds gebunden. Über den Parameter valueUpdate wird die Bindung derart deklariert, dass sie myval bei jedem Tastendruck setzt.

      mytext wiederum ist ein berechneter Wert, der sich im Wesentlichen aus myval ermittelt. An die Definition von mytext wird die Drosselung über die Methode extend angehängt. Damit verzögert Knockout.js eine Berechnung so lange, bis der Anwender eine gewisse Zeit nichts mehr eingegeben hat. Wie lange Knockout.js hier wartet, hängt von dem Parameter throttle ab. Der Wert ist die Anzahl der Millisekunden, die gewartet wird. In Code sieht das so aus:

      viewModel.mytext = ko.computed(function(){

      return viewModel.myval() }).extend({ throttle : 1000 });

      Bitte beachten Sie: Sie können diese Berechnung nicht innerhalb der JSON-Deklaration von viewModel ausführen. Versuchen Sie das, erhalten Sie eine Fehlermeldung. Sie müssen die Berechnung nach der Deklaration dem Objekt viewModel hinzufügen. Der Grund ist, dass Sie innerhalb der JSON-Deklaration keinen Zugriff auf das Objekt selbst haben. this zeigt zu diesem Zeitpunkt noch auf DOMWindow, also das umgebende Fensterobjekt. viewModel selbst ist noch nicht definiert.

      throttle lässt sich nun hervorragend für Ajax-Anfragen verwenden. Zum Beispiel so:

      viewModel.mytext = ko.computed(function(){

      $.getJSON('../jquerydata/service/index.php', {

      "value" : viewModel.myval() },

      function(da){

      console.log(da.toString());

      }

      );

      }).extend({ throttle : 1000 });

      Die Ajax-Funktion getJSON von jQuery wird erst dann aufgerufen, wenn der Anwender eine Sekunde keinen Text mehr eingegeben hat. Als URL-Parameter value wird der Wert von myval übermittelt. Die übergebene Callback-Funktion im Aufruf von getJSON stellt das Ergebnis dar. Hier ließe sich natürlich auch eine Observable setzen und damit das Ergebnis direkt in der View anzeigen.

      function(da){

      if (da.person)

      {

      viewModel.lastname(da.person.lastname);

      }

      }

      Wenn Sie Tipp 2 verwenden und sich den Inhalt des ViewModels anzeigen lassen, sehen Sie, dass sich bei der Eingabe in das input-Element nach dem Return schon etwas tut. Das Datenfeld lastname im ViewModel spiegelt den Wert im Control input wider.

      Auf einen Event reagieren

      Jetzt wissen Sie, wie Sie Daten in der View anzeigen oder wie Sie in die View eingegebene Daten von dort auslesen. Stellt sich nur die Frage, wie Sie auf Events wie einen Mausklick reagieren können, beispielsweise wenn der Anwender einen Knopf betätigt.

      Auch dafür ist Knockout.js selbstverständlich gerüstet. Die Ereignisbindung läuft genauso wie die Datenbindung. Sie fügen dem HTML-Code nur eine neue Anweisung hinzu:

      <button data-bind="click: buttonClicked">

      Klick mich

      </button>

      Laden Sie jetzt die HTML-Seite neu, erhalten Sie eine Fehlermeldung auf der Konsole: Die Datenbindung wird nicht verstanden. Das ist auch kein Wunder, denn das ViewModel verfügt über kein Feld, das es der Eigenschaft click: buttonClicked zuordnen kann.

      Es fehlt also noch das passende Feld. Nur würde ein Datenfeld in diesem Fall keinen Sinn machen; ein

Скачать книгу