Jetzt Knockout.js lernen: Observables erweitern

Im vergangenen Teil der Serie zu Knockout.js wurden benutzerdefinierte Bindungen behandelt. Dieser Teil beschäftigt sich nun damit, wie Observables auf eigene Bedürfnisse hin erweitert werden können. Knockout.js unterstützt das Lesen und Schreiben von Werten, als auch Benachrichtigungen bei Wertänderungen. In zahlreichen Fällen (zum Beispiel Validierung) möchte man dieses Verhalten jedoch erweitern. Dieser Beitrag zeigt, wie dies umgesetzt werden kann.

Extender zur Validierung erstellen

Knockout.js bietet mit Extendern eine Erweiterungsmöglichkeit an, sich an Observables zu hängen. Das nachfolgende Beispiel erweitert Observables durch die Möglichkeit einer Validierung.

Im ersten Schritt erstellen wir ein einfaches ViewModel, welches an eine View gebunden wird. Hier das ViewModel:

function BookViewModel(title, author, pages) {

    this.title = ko.observable(title).extend({ requiredField: "Please enter a title" });

    this.author = ko.observable(author).extend({ requiredField: "Please enter an author" });

    this.pages = ko.observable(pages).extend({ requiredField: "" });

}

 

var viewModel = new BookViewModel("Windows Presentation Foundation 4.5 - Einführung und Praxis", "Norbert Eder", 400);

ko.applyBindings(viewModel);

Und passend dazu die View:

<div id="bookform">

    <h3>Title</h3>

    <p>

        <input data-bind='value: title' />

    </p>

    <h3>Author</h3>

    <p>

        <input data-bind='value: author' />

    </p>

    <h3>Pages</h3>

    <p>

        <input data-bind='value: pages' />

    </p>

</div>

Soweit nichts Neues. Nun möchten wir aber, dass eingegebene Werte validiert werden. In diesem Fall beschränke ich mich darauf, Felder als benötigt zu definieren. Ein Extender wird daher benötigt. Um einen Extender zu schreiben muss ko.extenders um eine Funktion erweitert werden, nennen wir sie requiredField. Diese enthält als Parameter das Ziel der Erweiterung und eine Nachricht (die für die Anzeige einer Meldung verwendet werden kann).

ko.extenders.requiredField = function(target, message) {   

    target.hasError = ko.observable();

    target.validationMessage = ko.observable();

 

    function validate(newValue) {

       target.hasError(newValue ? false : true);

       target.validationMessage(newValue ? "" : message || "* required");

    }

 

    validate(target());

    target.subscribe(validate);

 

    return target;

};

Der Extender hängt dem Ziel zwei Eigenschaften hasError und validationMessage um. Die erste beschreibt, ob ein Validierungsfehler vorliegt, die zweite, welcher Fehler dies genau ist. Zusätzlich wird eine Funktion validate benötigt, welche die Validierung schlussendlich durchführt. Dies ist in diesem Beispiel recht einfach. So muss lediglich auf Vorhandensein eines Wertes geprüft werden. Ist dies nicht der Fall wird die über den Parameter message übergegebene Meldung angezeigt – wurde keine eigene Meldung übergeben, wird ein Fallback auf eine Standardmeldung verwendet.

Via validate(target()); wird eine initiale Validierung durchgeführt. Per target.subscribe(validate); wird ein Abonnement hinsichtlich Wertänderungen hinzugefügt, damit auch in diesen Fällen die Validierung durchgeführt wird.

Anschließend wird das ursprüngliche Observable zurück geliefert. Das war alles, was auf JavaScript-Seite zu implementieren war. Nun ist noch die View anzupassen, um etwaige Meldungen sichtbar zu machen.

<div id="bookform">

    <h3>Title</h3>

    <p data-bind="css: { error: title.hasError }">

        <input data-bind='value: title, valueUpdate: "afterkeydown"' />

        <span data-bind='visible: title.hasError, text: title.validationMessage'> </span>

    </p>

    <h3>Author</h3>

    <p data-bind="css: { error: author.hasError }">

        <input data-bind='value: author, valueUpdate: "afterkeydown"' />

        <span data-bind='visible: author.hasError, text: author.validationMessage'> </span>

    </p>

    <h3>Pages</h3>

    <p data-bind="css: { error: pages.hasError }">

        <input data-bind='value: pages, valueUpdate: "afterkeydown"' />

        <span data-bind='visible: pages.hasError, text: pages.validationMessage'> </span>

    </p>

</div>

Für die Erweiterung der View wurden insgesamt drei Schritte unternommen:

  1. Für die input-Felder wird die Aktualisierung des Wertes im ViewModel durch valueUpdate auf afterkeydown geändert, damit jede Änderung sofort im ViewModel wirksam wird und so schon zur Eingabe eine Validierung stattfinden kann.
  2. Es wird ein span-Element eingeführt. Dieses enthält eine visible-Bindung auf die Eigenschaft hasError – ist also nur sichtbar, wenn ein Validierungsfehler aufgetreten ist. Der anzuzeigende Wert des span-Elementes wird auf die validationMessage gebunden.
  3. Die umschließenden p-Tags wurden um eine css-Bindung erweitert. Dadurch wird bei Vorhandensein eines Validierungsfehlers eine CSS-Klasse error auf das Element gehängt, wodurch ein Styling einfach gemacht wird. So sieht es aus:

Knockout.js: Validierung per Extender

    Download / Showcase

    Das Beispiel kann unter jsfiddle.net/zHFEU/ getestet und bezogen werden. Untenstehend findet sich das JSFiddle in eingebundener Form, benötigt aber einen Browser ungleich IE.

    Fazit

    Dieses Beispiel hat gezeigt, wie einfach es möglich ist, ein Verhalten á la Validierung per Knockout.js und Extender zu realisieren. Auch hier gilt wieder, dass die Zuständigkeiten sauber getrennt sind und einfach gewartet werden.

    Jetzt Knockout.js lernen: Die Serie

    Veröffentlicht von Norbert Eder

    Ich bin ein leidenschaftlicher Softwareentwickler. Mein Wissen und meine Gedanken teile ich nicht nur hier im Blog, sondern auch in Fachartikeln und Büchern.

    Beteilige dich an der Unterhaltung

    3 Kommentare

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

    1. Hallo Florian,

      und hier findest du meine Variante zu deiner Anregung: devtyr.norberteder.com/post/Jetzt-Knockoutjs-lernen-Formularvalidierung-mit-Undo.aspx

      Freue mich auf deine Anmerkungen/Anregungen :)

    2. Hallo Norbert!

      Interessant wäre noch ein Save-Button, der nur aktiv ist, wenn es keine Fehler auf dem gesamten Formular mehr gibt, sowie ein Cancel- bzw. Undo-Button der bei eventuellen Fehlern, die Werte zurücksetzt auf den ursprünglichen Wert.

      Danke! Und bitte mach mit deiner Serie weiter!

    Cookie-Einstellungen
    Auf dieser Website werden Cookie verwendet. Diese werden für den Betrieb der Website benötigt oder helfen uns dabei, die Website zu verbessern.
    Alle Cookies zulassen
    Auswahl speichern
    Individuelle Einstellungen
    Individuelle Einstellungen
    Dies ist eine Übersicht aller Cookies, die auf der Website verwendet werden. Sie haben die Möglichkeit, individuelle Cookie-Einstellungen vorzunehmen. Geben Sie einzelnen Cookies oder ganzen Gruppen Ihre Einwilligung. Essentielle Cookies lassen sich nicht deaktivieren.
    Speichern
    Abbrechen
    Essenziell (1)
    Essenzielle Cookies werden für die grundlegende Funktionalität der Website benötigt.
    Cookies anzeigen