Sie sind hier: Weblog

Mit asynchronen Validatoren ab AngularJS 1.3 Eingaben im Hintergrund prüfen

Foto ,
28.01.2015 23:26:00

Neben den im letzten Beitrag beschriebenen synchronen Validatoren bietet AngularJS ab Version 1.3 auch die Möglichkeit, mit asynchronen Validatoren Eingaben im Hintergrund zu prüfen. Diese verwaltet ng-model über die Eigenschaft $asyncValidators. Sie kommen nur zum Einsatz, wenn weder Parser noch synchrone Validatoren einen Validierungsfehler gemeldet haben. Wie bei ihren synchronen Gegenstücken handelt es sich bei asynchronen Validatoren auch lediglich um Funktionen, denen AngularJS den zu validierenden Wert übergibt. Im Gegensatz zu synchronen Validatoren liefern asynchrone Validatoren jedoch ein Promise retour. Dabei handelt es sich um ein Objekt, welches eine asynchrone Operation repräsentiert und Callbacks anstößt, die über das Ergebnis dieser asynchronen Operation informieren.

Das nächste Listing zeigt eine Direktive, welche einen asynchronen Validator bereitstellt. Sie ähnelt den Direktiven in den vorangegangenen Abschnitten, weswegen das betrachtete Beispiel hier auch nur auf die Unterschiede dazu eingeht. Der eingerichtete Validator ruft einen HTTP-Service auf, um den übergebenen Wert zu prüfen. Dazu nutzt er die Methode get des $http-Services. Diese Funktion liefert ein Promise retour. Unter Verwendung dessen then-Funktion registriert der Validator einen Handler, den AngularJS anstoßen soll, wenn die angeforderten Daten vorliegen. Das Ergebnis von then ist ein weiteres Promise, welches der Validator retourniert. Der Handler nimmt, wie gewohnt, die vom HTTP-Service erhaltenen Daten entgegen. Handelt es sich dabei um einen Wert, den JavaScript als false ausgewertet, liefert er einen Promise, der über einen negativen Ausgang einer asynchronen Operation informiert, retour. Diesen Promise erzeugt er mit dem von AngularJS bereitgestellten Service $q. Liefert der Callback keinen eigenen Promise retour, geht AngularJS davon aus, dass die asynchrone Validierungsoperation erfolgreich verlaufen ist.

app.directive(flughafenAsyncValidator, function($http, $q, $log) { 

    return {
        require: ngModel,
        link: function (scope, element, attrs, ngModel) {

            ngModel.$asyncValidators.flughafen = function(value) {

                $log.log("validate flughafen: " + value);
                var urlParams = { name: value, delay: 0 };

                var url = "http://flugdemo.azurewebsites.net/api/Flughafen";

                return $http.get(url, { params: urlParams }).then(function(response) {

                    $log.log("got data from service: " + response.data);
                    if (!response.data) {
                        return $q.reject();
                    }
                });
            }
        }
    }
});

Wie auch synchrone Validatoren registriert der Entwickler ihre aynchronen Gegenstücke, indem der die dafür bereitgestellte Direktive für ein Eingabefeld aktiviert (siehe nächstest Listing). Der Model-Controller, welcher dieses Eingabefeld repräsentiert, gibt über die Eigenschaft $pending darüber Auskunft, ob er noch auf das Ergebnis von asynchronen Validatoren wartet. Unter Verwendung dieser Eigenschaft kann der Entwickler den Benutzer darüber informieren, dass die Validierung noch nicht abgeschlossen ist.

<div ng-app="flug">

    <form ng-controller="editFlugCtrl" name="form" id="form">
        <div class="form-group">
            <label for="von">Von</label>
            <div><input class="form-control" ng-model="vm.flug.von" required flughafen-async-validator name="von" id="von" /></div>
            <div ng-show="form.von.$pending">Validierung wird durchgeführt!</div>
            <div ng-show="form.von.$error.required">Pflichtfeld!</div>
            <div ng-show="form.von.$error.flughafen">Kein gültiger Flughafen!</div>
        </div>
    </form> 

</div>