2014-06-17 7 views
8

Ich habe eine Direktive für benutzerdefinierte Validierung (überprüfen Sie, ob ein Benutzername noch nicht existiert). Die Validierung verwendet den $ http-Dienst, um den Server nach dem Vorhandensein des Benutzernamens zu fragen. Daher ist die Rückgabe ein Zusicherungsobjekt. Dies funktioniert fantastisch für die Validierung. Das Formular ist ungültig und enthält die Datei myform. $ Error.usernameVerify, wenn der Benutzername bereits vergeben ist. Allerdings ist user.username immer undefiniert, so dass es meine ng-model-Direktive bricht. Ich denke, das liegt wahrscheinlich daran, dass die Funktion in .success ihren eigenen Bereich erstellt und der Rückgabewert nicht auf den Controllern $ scope verwendet wird. Wie behebe ich das, damit die ng-model-Bindung noch funktioniert?Async-Dienst in der benutzerdefinierten AngularJS-Validierungsdirektive aufrufen

commonModule.directive("usernameVerify", [ 
    'userSvc', function(userSvc) { 
     return { 
      require: 'ngModel', 
      scope: false, 
      link: function(scope, element, attrs, ctrl) { 
       ctrl.$parsers.unshift(checkForAvailability); 
       ctrl.$formatters.unshift(checkForAvailability); 

       function checkForAvailability(value) { 
        if (value.length < 5) { 
         return value; 
        } 
        // the userSvc.userExists function is just a call to a rest api using $http 
        userSvc.userExists(value) 
         .success(function(alreadyUsed) { 
          var valid = alreadyUsed === 'false'; 
          if (valid) { 
           ctrl.$setValidity('usernameVerify', true); 
           return value; 
          } 
          ctrl.$setValidity('usernameVerify', false); 
          return undefined; 
         }); 
       } 
      } 
     } 
    } 
]); 

Hier ist meine Vorlage:

<div class="form-group" ng-class="{'has-error': accountForm.username.$dirty && accountForm.username.$invalid}"> 
    <label class=" col-md-3 control-label">Username:</label> 
    <div class="col-md-9"> 
     <input name="username" 
       type="text" 
       class="form-control" 
       ng-model="user.username" 
       ng-disabled="user.id" 
       ng-minlength=5 
       username-verify 
       required /> 
     <span class="field-validation-error" ng-show="accountForm.username.$dirty && accountForm.username.$error.required">Username is required.</span> 
     <span class="field-validation-error" ng-show="accountForm.username.$dirty && accountForm.username.$error.minlength">Username must be at least 5 characters.</span> 
     <span class="field-validation-error" ng-show="accountForm.username.$dirty && accountForm.username.$error.usernameVerify">Username already taken.</span> 
    </div> 
</div> 

Antwort

4

Um dies zu erhalten zu arbeiten, ich hinzufügen benötigt „Rückgabewert“; außerhalb des asynchronen Aufrufs. Code unten.

commonModule.directive("usernameVerify", [ 
    'userSvc', function(userSvc) { 
     return { 
      require: 'ngModel', 
      scope: false, 
      link: function(scope, element, attrs, ctrl) { 
       ctrl.$parsers.unshift(checkForAvailability); 
       ctrl.$formatters.unshift(checkForAvailability); 

       function checkForAvailability(value) { 
        if (value.length < 5) { 
         return value; 
        } 
        userSvc.userExists(value) 
         .success(function(alreadyUsed) { 
          var valid = alreadyUsed === 'false'; 
          if (valid) { 
           ctrl.$setValidity('usernameVerify', true); 
           return value; 
          } 
          ctrl.$setValidity('usernameVerify', false); 
          return undefined; 
         }); 
        // Below is the added line of code. 
        return value; 
       } 
      } 
     } 
    } 
]); 
+1

Das ist falsch. Check out http://blog.brunoscopelliti.com/form-validation-the-angularjs-way –

+0

Das Problem mit diesem Ansatz ist, dass die checkForAvailability-Funktion (mit Ihrem Wert) sofort zurückgibt, da die userExists-Funktionen eine Zusage, die wird später erfüllt werden. –

16

Angular verfügt über eine eigene Reihe von asyncValidators $ dieser Situation genau:

siehe https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { 
var value = modelValue || viewValue; 

// Lookup user by username 
return $http.get({url:'/api/users/' + value}). 
    then(function resolved() { 
    //username exists, this means validation fails 
    return $q.reject('exists'); 
    }, function rejected() { 
    //username does not exist, therefore this validation passes 
    return true; 
    }); 
}; 
+6

Hinweis: Dies ist seit Angular 1.3.0 verfügbar –

Verwandte Themen