Как добавить ошибку в список ошибок проверки формы в angular?

Я использую ng-messages для проверки полей регистрационной формы, но у меня проблема: я не могу проверить, занято ли имя пользователя, пока не отправлю запрос на регистрацию на сервер. В настоящее время у меня есть этот тип кода:

UserPool.signUp(vm.form.username, vm.form.password, attributes)
    .then(function (result) {
        $state.go('app.pages_auth_confirm', {
            user: result.user
        });
    })
    .catch(function () {
        $scope.registerForm.username.$invalid = true;
        $scope.registerForm.username.$error.usernameAlreadyExists = true;
    });

и HTML:

<input name="username" ng-model="vm.form.username" placeholder="Name" required>
<div ng-messages="registerForm.username.$error" role="alert">
    <div ng-message="required">
        <span>Username field is required</span>
    </div>
    <div ng-message="usernameAlreadyExists">
        <span>User with this username already exists</span>
    </div>
</div>

и это работает, но я хочу знать, как правильно реализовать эту функциональность. Форма регистрации также имеет много других полей, и изменение некоторых из них вручную для отображения ошибки не кажется хорошей идеей. Я также провел некоторое исследование о проверках и сообщениях в angular и узнал о пользовательской проверке и $asyncValidators, но я не могу использовать эту функцию ни потому, что, как я понял, мне понадобится какой-то API для получения информации только об используемых именах пользователей, но У меня такой возможности нет, как я уже сказал, я не могу проверить занято ли имя пользователя, пока не отправлю запрос на регистрацию. Так может ли кто-нибудь сказать мне, что мне делать? Как правильно работать с такой проверкой?


person GROX13    schedule 03.10.2016    source источник


Ответы (3)


Чтобы добиться этого в angular way, создайте Directive в user-name input, чтобы проверить наличие unique validation, и factory, чтобы сделать вызов API для проверки проверки имени пользователя.

<input name="username" ng-model="vm.form.username" placeholder="Name" required name="username" unique> 

<div ng-messages="registerForm.username.$error" role="alert">
    <div ng-message="required">
        <span>Username field is required</span>
    </div>
    <div ng-message="unique">
        <span>User with this username already exists</span>
    </div>
</div>

directive может быть примерно таким,

В этой директиве мы внедрили фабрику с именем usernameservice, которая возвращает обещание true или false.

myApp.directive('unique', function(usernameservice) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$asyncValidators.unique = usernameservice;
    }
  };
});

Вот factory, куда идет ваш вызов API.

myApp.factory('usernameservice', function($q, $http) {
  return function(username) {
    var deferred = $q.defer();

    // your api vall goes her
    $http.get('/api/users/' + username).then(function() { // 
      // Found the user, therefore not unique.
      deferred.reject();
    }, function() {
      // User not found, therefore unique!
      deferred.resolve();
    });

    return deferred.promise;
  }
});

Теперь сообщение будет отображаться каждый раз, когда значение будет изменено, давайте отложим проверку, чтобы, если пользователь вводит больше букв, она вызывалась, давайте использовать для этого ng-model-option debounce.

<input name="username" ng-model="vm.form.username" placeholder="Name" required name="username" unique ng-model-options="{ debounce: 100 }">  
person Sravan    schedule 03.10.2016
comment
Невозможно узнать, действительно ли имя пользователя, если я не отправлю запрос на регистрацию со всеми полями (имя пользователя, пароль, адрес электронной почты, телефон и т. д.), и, как я понимаю, такое решение не будет работать, только способ узнать, если имя пользователя действителен после того, как пользователь нажмет кнопку регистрации, тогда я получу ответ, который будет содержать статус 400 с сообщением об ошибке. Имя пользователя уже занято! и это единственный способ узнать, что имя пользователя уже используется. - person GROX13; 03.10.2016
comment
хорошо, но вы не хотите добавлять асинхронную проверку в форму в контроллере, как в примере? - person Sravan; 03.10.2016
comment
вы получаете имя поля ошибки в ответ на регистрацию, например, имя пользователя уже занято, такое сообщение? - person Sravan; 03.10.2016
comment
@Sravan отличный код, пожалуйста, не удаляйте. @ GROX13 этот код отвечает на ваш вопрос. Если вам нужно только что-то вроде отображения/скрытия текста, используйте ng-show после отправки с возвратом ошибки. - person Joao Polo; 03.10.2016
comment
Я хотел бы добавить асинхронную проверку, но это не сработает, потому что у меня нет возможности проверить, действительно ли имя пользователя, если я не отправлю запрос на регистрацию на сервер, а это означает, что если я отправлю этот запрос из асинхронного валидатора, если имя пользователя не выбранный пользователь будет зарегистрирован без нажатия кнопки регистрации. - person GROX13; 03.10.2016
comment
сделать одно то, после изменения значения для имени пользователя, сделать запрос на регистрацию API и когда вы получите ответ, проверьте в ответе, если вы получите имя пользователя, ошибка. если это так, отклоните запрос, иначе разрешите его. - person Sravan; 03.10.2016
comment
Я не могу понять, как это решит мою проблему? В этом случае пользователь будет зарегистрирован в любом случае, не нажимая кнопку регистрации. Вы говорите мне отправить запрос на регистрацию от валидатора, что кажется мне ужасной идеей. Я согласен, что вы написали отличный код выше, но в моем случае это не будет полезно. - person GROX13; 03.10.2016
comment
Мне нужно как-то добавить ошибку проверки в блоке catch, но мне не очень нравится помещать ее вручную в массив $error. - person GROX13; 03.10.2016
comment
в чем моя идея, отправьте только параметр имени пользователя в запрос на регистрацию, так как остальные поля в любом случае будут не заполнены, вы всегда будете получать сообщение об ошибке, если имя пользователя уже зарегистрировано, тогда вы можете наконец отправить все поля - person Sravan; 03.10.2016
comment
проверьте пользовательскую проверку, приведенную в официальной документации angular, в ней также упоминается тот же способ сделать это. проверка формы - person Sravan; 03.10.2016
comment
Да, это звучит хорошо, мне придется это сделать, если я не смогу исправить это по-другому, но в любом случае я хотел бы также избежать создания дополнительного сетевого трафика. - person GROX13; 03.10.2016

Такой код работает только для добавления ошибки проверки в массив:

$scope.registerForm.username.$setValidity("usernameAlreadyExists", false);

это должно быть вызвано в блоке catch следующим образом:

...
.catch(function () {
    $scope.registerForm.username.$setValidity("usernameAlreadyExists", false);
});

Этот код не помечает никакие переменные формы вручную, вместо этого он использует метод интерфейса $setValidity, который устанавливает все необходимые переменные по мере необходимости.

person GROX13    schedule 03.10.2016

В вашем html поместите свою форму в

<ng-form name="myFormName">
    ... your form...
</ng-form>

Этот тег представляет собой угловую форму <form></form>. И вы можете поместить немного <ng-form> внутрь <ng-form> и т. д., если это необходимо.

Затем поместите валидатор в свой html-компонент, например «required»:

<ng-form name="myFormName">
    <input type="text" name="myinput" ng-required="true">
</ng-form>

Здесь класс «недействительный» будет помещен angular на ваш компонент, если он недействителен, т. Е. Не заполняет в нашем случае.

Затем вы можете настроить свой компонент для «недопустимого» класса.

Если вы хотите проверить все ошибки формы, вы можете отобразить переменную $error. В нашем примере вы можете напечатать myFormName.$error и проверить статус с помощью myFormName.$valid или myFormName.$invalid.

person M.Be    schedule 03.10.2016
comment
Хм... кажется, я неправильно понял ваше последнее предложение, когда отвечал на свой первый черновик... Итак, вы вообще не можете изменить HTML-сторону? - person M.Be; 03.10.2016
comment
Я могу изменить HTML, это не вопрос этого вопроса. У меня нет никаких проблем с html. Я просто не люблю что-то отмечать вручную. Даже не с registerForm.username.$invalid по true. Я отредактирую вопрос и добавлю HTML. Я думаю, это хорошая идея. - person GROX13; 03.10.2016