Sie sind hier: Weblog

Werte mit AngularJS in Abhängigkeit anderer Werte validieren

Foto ,
05.10.2014 23:17:00

Die Tage wurde ich gefragt, wie man mit AngularJS Werte in Abhängigkeit von anderer Werte validieren kann. Anwendungsfälle dafür sind Eingaben die zur Bestätigung doppelt erfasst werden müssen oder logische Abhängigkeiten zwischen Zahlen und Datumswerten, bei denen ein Startwert kleiner oder gleich einem Endwert zu sein hat.

Da Validatoren in AngularJS eigentlich benutzerdefinierte Direktiven sind, kann man sich hier auf die Möglichkeiten der Datenbindung mit isolierten Scopes stützen. Das nachfolgende Beispiel zeigt eine solche Direktive mit dem Namen isSameAs, welche einen Parser zum Validieren einrichtet. Interessant ist dabei die Deklaration des Scopes. Die Eigenschaft isSameAs repräsentiert den Namen einer Variablen innerhalb des Scopes. Ihr Wert legt fest, dass derselbe Name für ein HTML-Attribut zu nutzen ist, an das der zu vergleichende Ausdruck zu übergeben ist. Durch die Normalisierung der Namen kommt schlussendlich in HTML jedoch die Schreibweise is-same-as zum Einsatz. Das Gleichheitszeichen am Beginn des Wertes gibt an, dass an das genannte Attribut ein auswertbarer Ausdruck zu übergeben ist. Ein @ würde hingegen bedeuten, dass AngularJS lediglich einen beliebigen String erwartet und ein & kommt für Funktionen zum Einsatz. Beschränkt man sich im Übrigen beim Wert auf eines der drei genannten Zeichen (z. B. scope: { isSameAs: =}), geht AngularJS davon aus, dass der Name der Variable dem Namen des Attributs entspricht. Da dies hier der Fall ist, könnte man auch mit dieser kürzeren Schreibweise vorlieb nehmen.

Innerhalb der Link-Funktion registriert die Direktive bei der benachbarten ngModel-Direktive, welche sich um die Datenbindung des zu validierenden Ausdrucks kümmert, einen Parser. Dieser Parser meldet mit der Funktion $validity zurück, ob die Validierung erfolgreich verlaufen ist. Den vom Parser retour gelieferten Wert schreibt AngularJS ins Model zurück.

app.directive("isSameAs", function () {

    return {
        require: ngModel,
        scope: {
            isSameAs: =isSameAs
                // Ausdruck von Attribut is-same-as an 
                // scope-interne Variable isSameAs binden
        },
        link: function (scope, elm, attrs, ctrl) {

            // Parser: View --> Model
            ctrl.$parsers.unshift(function (viewValue) {

                if (viewValue === scope.isSameAs) {
                    ctrl.$setValidity(isSameAs, true);
                    return viewValue;
                }
                else {
                    ctrl.$setValidity(isSameAs, false);
                    return undefined;
                }
            });
        }
    };

});

Das nachfolgende Listing zeigt, wie die besprochene benutzerdefinierte Direktive anzuwenden ist. Es wendet sie auf das zweite Passwort an. Als Datenbindungsausdruck enthält die Direktive den Wert des ersten Passwortes. Im Fehlerfall blendet das Beispiel mit ngShow eine Fehlermeldung ein.

<div>Passwort:</div>
<input name="password" ng-model="vm.password">

<div>Passwort wiederholen:</div>
<input name="password2" ng-model="vm.password2" is-same-as="vm.password">
<div class="error" ng-show="form.password2.$invalid">Die beiden Passwörter müssen gleich sein!</div>