2014-06-17 13 views
8

Mam dyrektywę do sprawdzania poprawności niestandardowej (sprawdź, czy nazwa użytkownika jeszcze nie istnieje). Walidacja korzysta z usługi $ http, aby zapytać serwer, czy nazwa użytkownika istnieje, więc zwrot jest obietnicą. Działa to fantastycznie do sprawdzania poprawności. Formularz jest nieprawidłowy i zawiera identyfikator myform. $ Error.usernameZawartość, gdy nazwa użytkownika jest już zajęta. Jednak user.username jest zawsze niezdefiniowany, więc łamie moją dyrektywę ng-model. Myślę, że jest tak prawdopodobnie dlatego, że funkcja w .success tworzy swój własny zakres, a wartość zwracana nie jest używana w kontrolerach $ scope. Jak mogę to naprawić, aby wiązanie modelu ng nadal działało?Wywołanie usługi asynchronicznej w niestandardowej dyrektywie walidacyjnej AngularJS

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; 
         }); 
       } 
      } 
     } 
    } 
]); 

Oto mój szablon:

<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> 

Odpowiedz

4

Aby uzyskać to do pracy, musiałem dodać "wartości zwracanej;" poza połączeniem asynchronicznym. Kod poniżej.

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

To jest błędne. Sprawdź http://blog.brunoscopelliti.com/form-validation-the-angularjs-way –

+0

Problem z tym podejściem polega na tym, że funkcja checkForAvailability natychmiast zwróci (z twoją wartością), ponieważ funkcje userExists zwracają obietnicę, która będzie spełnić się później. –

16

kątowa posiada dedykowany tablicę $ asyncValidators właśnie z tej sytuacji:

zobaczyć 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

Uwaga: Jest to dostępne od wersji Angular 1.3.0 –

Powiązane problemy