Угловая дистанционная форма не отображает ошибку

Я создал угловую форму, которая отображает входные ошибки проверки, полученные с сервера. Мое решение работает хорошо, за исключением одной маленькой проблемы. Если я отправляю форму без значения, после загрузки страницы я получаю правильный ответ от моего сервера, т.е. 422, но ошибка проверки не отображается. Если я затем начну вводить значение на входе, ошибка проверки мигает и исчезает.

Я почти уверен, что это как-то связано с моей директивой, но я не уверен, как это исправить. Это мой текущий код директивы:

var appServices = angular.module('webFrontendApp.directives', []);

appServices.directive('serverError', function(){
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope,element,attrs,ctrl){
      element.on('change keyup', function(){
        scope.$apply(function(){
          ctrl.$setValidity('server', true);
        });
      });
    }
  };
});

Я думаю, что проблема в элементе element.on ("change keyup".... этого кода. Вот почему сообщение об ошибке мигает, когда я начинаю печатать. Также, когда я изменяю это на "change" вместо "change keyup"), сообщение об ошибке отображается постоянно, когда я начинаю печатать.

Кто-нибудь имеет представление о том, как я могу отобразить сообщение об ошибке, даже если я не вводил какое-либо значение во входные данные перед отправкой в ​​первый раз?

ОБНОВЛЕНИЕ КАК КОММЕНТАРИЙ

Вот моя форма:

<form ng-submit="create(memberData)" name="form" novalidate>
  <div class = "row form-group" ng-class = "{ 'has-error' : form.email.$dirty && form.email.$invalid }">
     <input type="text" ng-model="memberData.email" placeholder="janedoe@mail.com"  name="email" class="col-xs-12 form-control" server-error>

     <span class="errors" ng-show="form.email.$dirty && form.email.$invalid">
       <span class="glyphicon glyphicon-remove form-control-feedback"></span>
       <span ng-show="form.email.$error.server">{{errors.email}}</span>
     </span>
  </div>
  <div class="row">
    <button type="submit" class="btn btn-danger col-xs-12">Join Private Beta</button>
  </div>
</form>

И мой контроллер:

$scope.memberData = {};
$scope.create = function() {
    var error, success;
    $scope.errors = {};
    success = function() {
      $scope.memberData = {};
    };    
    error = function(result) {
        angular.forEach(result.data.errors, function(errors, field) {
            $scope.form[field].$setValidity('server', false);
            $scope.errors[field] = errors.join(', ');
        });    
    };



    BetaMember.save({ beta_member: { email: $scope.memberData.email || "" }}).$promise.then(success, error);

};

2 ответа

Решение

Кажется, что был чрезвычайно простой обходной путь. Поскольку у меня был фильтр form.email.$ Dirty на мой взгляд, ошибка не будет отображаться, если пользователь нажал на кнопку отправить, не щелкнув сначала форму.

После удаления form.email.$ Dirty и наличия только form.email.$ Недействительным, он работает отлично. Я думаю, что в моем случае этого достаточно, так как эта проверка зависит от ответа сервера и не будет запущена до отправки формы. Объект ошибки также очищается в моем контроллере, гарантируя, что страница не загружает ошибку при первой загрузке.

Поскольку сама форма не имеет метода $setValidity, поскольку не имеет ng-модели и предполагает, что ошибка сервера не относится ни к одному полю (в этом случае предпочтителен метод $setValidity), я думаю, что самое простое решение может быть этим:

Создайте форму с некоторой случайной проверкой (для этого просто нужно указать хотя бы имя пользователя) и div, который может отображать пользовательскую ошибку сервера.

<div ng-controller="AppCtrl">

    <form novalidate name="createForm">

        <div class="inputWrap">

            <input ng-model="name" name="name" type="text" required placeholder="John Doe">

            <span ng-if="createForm.name.$dirty && createForm.name.$invalid">
                Some kind of error!
            </span>

        </div>

        <div ng-if="serverError">
            {{ serverError.message }}
        </div>

        <input
            value="Join Private Beta"
            ng-disabled="createForm.$invalid || serverError" 
            ng-click="create()"
            type="button">

    </form>

</div> 

Затем в вашем контроллере вы можете добавить метод create, который имеет дело с YourService (должен возвращать обещание), и если ответом будет сбой, вы можете создать простой объект с пользовательским сообщением об ошибке внутри сервера, которое также будет полезно для отключения кнопки формы, если тебе надо.

var AppCtrl = function($scope, YourService){

    // Properties

    // Shared Properties

    // Methods
    function initCtrl(){}

    // Shared Methods
    $scope.create = function(){

        YourService.makeCall().then(function(response){

            // Success!

            // Reset the custom error
            $scope.serverError = null;

        }, function(error){

            // Do your http call and then if there's an error
            // create the serverError object with a message
            $scope.serverError = {
                message : 'Some error message'
            };

        })

    };

    // Events

    // Init controller
    initCtrl();

};

AppCtrl.$inject = [
    '$scope',
    'YourService'
];

app.controller('AppCtrl', AppCtrl);

Я имею в виду, что здесь очень простой фрагмент, я просто хотел привести пример. Ничего сложного, но вы можете масштабировать это к чему-то большему.

Другие вопросы по тегам