#angularjs #validation #angularjs-directive
#angularjs #проверка #angularjs-директива
Вопрос:
У меня есть директива для пользовательской проверки (убедитесь, что имя пользователя еще не существует). Проверка использует службу $ http, чтобы запросить сервер, существует ли имя пользователя, поэтому возвращаемый объект является объектом promise . Это работает фантастически для проверки. Форма недопустима и содержит myform.$error.usernameVerify, когда имя пользователя уже занято. Однако user.username всегда не определен, поэтому он нарушает мою директиву ng-model. Я думаю, это, вероятно, потому, что функция в .success создает собственную область видимости, а возвращаемое значение не используется в $scope контроллеров. Как мне это исправить, чтобы привязка к ng-модели все еще работала?
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;
});
}
}
}
}
]);
Вот мой шаблон:
<div class="form-group" ng-class="{'has-error': accountForm.username.$dirty amp;amp; 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 amp;amp; accountForm.username.$error.required">Username is required.</span>
<span class="field-validation-error" ng-show="accountForm.username.$dirty amp;amp; accountForm.username.$error.minlength">Username must be at least 5 characters.</span>
<span class="field-validation-error" ng-show="accountForm.username.$dirty amp;amp; accountForm.username.$error.usernameVerify">Username already taken.</span>
</div>
</div>
Ответ №1:
Angular имеет выделенный массив $asyncValidators именно для этой ситуации:
см. 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;
});
};
Комментарии:
1. Примечание: Это доступно с Angular 1.3.0
Ответ №2:
Чтобы заставить это работать, мне нужно было добавить «возвращаемое значение;» вне асинхронного вызова. Код ниже.
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. Это неверно. Проверьте blog.brunoscopelliti.com/form-validation-the-angularjs-way
2. Проблема с этим подходом заключается в том, что функция checkForAvailability немедленно вернет (с вашим значением), поскольку функции userExists возвращают обещание, которое будет выполнено позже.