AngularJS -在元素绑定上验证可用的邮件

AngularJS - validating available email on element bind

本文关键字:验证 元素 绑定 AngularJS      更新时间:2023-09-26

我在'email'输入字段上使用'required'和'email'验证器。验证器使用解析器和格式化器,它们工作得很好。然而,我也有一些验证'bind'事件。

指令如下:

angular.module('simpleRepairApp')
  .directive('uniqueEmail', function (Checker) {
    return {
      require:'ngModel',
      restrict:'A',
      link:function ($scope, element, attrs, model) {    
        var last = '';
        var current = '';    
        element.bind('blur', function() {    
          current = element.val();    
          console.log(current, last);    
          if(current !== last){
            Checker.email({ email:current }).then(
              function(response) {
                model.$setValidity('uniqueEmail', response.available);
              }
            );
          }    
          last = current;    
        });    
      }
  };
});

我需要检查电子邮件是否已经存在于数据库中或用户点击字段后不存在(我不想检查每次按键或更改)。

我遇到的问题是,在执行唯一验证后,它显示唯一的错误消息,但在您键入纠正电子邮件后,模型值保持未定义。您必须单击退出输入,然后重新定义模型中的值。

任何人都可以帮我解决这个问题,它快把我逼疯了!:)

工作解决方案:

angular.module('simpleRepairApp')
  .directive('emailUnique', function () {
    return {
      restrict: 'E',
      require: ['form', 'ngModel'],
      scope: {
        'form': '=form',
        'model': '=ngModel',
        'labelClass': '@',
        'inputClass': '@'
      },
      compile: function(element, attrs)
      {
        if (!attrs.labelClass) { attrs.labelClass = 'col-sm-4'; }
        if (!attrs.inputClass) { attrs.inputClass = 'col-sm-8'; }
        attrs.required = attrs.required == 'true';
      },
      controller: function($scope, Checker) {
        $scope.checkEmail = function() {
          var email = $scope.form.email.$viewValue;
          var checkField = $scope.form.emailCheck;
          Checker.email({ email:email }).then(
            function(response) {
              checkField.$setValidity('unique', response.available);
              $scope.form.$setValidity('check', true);
              checkField.hasVisit = true;
            }
          );
        };
        $scope.setUnchecked = function() {
          console.log($scope.form);
          $scope.form.emailCheck.hasVisited = false;
          $scope.form.$setValidity('check', false);
          $scope.form.emailCheck.$setValidity('unique', true);
        };
      },
      template: '<div ng-class="{ ''has-error'' : !form.email.$valid || !form.emailCheck.$valid }">' +
                  '<label class="{{ labelClass }} control-label required" for="email" translate>E-mail</label>' +
                  '<div class="{{ inputClass }}">' +
                    '<input name="email" class="form-control" type="email" id="email" ng-model="model" ng-change="setUnchecked()" ng-blur="checkEmail()" ng-required="true" autocomplete="off">' +
                    '<div class="help-block" ng-show="(!form.email.$valid || !form.emailCheck.$valid) && !form.email.$pristine">' +
                      '<div ng-messages="form.email.$error">' +
                        '<div ng-message="required"><span translate>Please enter your e-mail.</span></div>' +
                        '<div ng-message="email"><span translate>Please enter a valid e-mail.</span></div>' +
                      '</div> ' +
                      '<div ng-messages="form.emailCheck.$error">' +
                        '<div ng-message="check"><span translate>E-mail will be checked upon blur.</span></div>' +
                        '<div ng-message="unique"><span translate>This e-mail is already in use.</span></div>' +
                      '</div> ' +
                    '</div>' +
                    '<input name="emailCheck" type="hidden" class="form-control" ng-model="checked">' +
                    '<div class="help-block" ng-messages="form.emailCheck.$error" ng-show="!form.emailCheck.$valid">' +
                    '</div>' +
                  '</div>' +
                '</div>'
    };
  });

我认为你可能是复杂的事情一点,使一个指令,为什么不简单地添加一个监视器到您的控制器?

注意:我不熟悉这些方法是否适合您,但是我添加它们是为了说明不绑定到"blur"事件的目的,而是让事件在MODEL更改时被触发。这就是angular的设计目的。我还假设您的检查器正在正确处理承诺

第一个替代方法(使用$watch)

<form name="myForm" ng-controller="ExampleController">
    <input type="email" name="input" ng-model="text" required />
</form>

然后在你的ng-app控制器中:

function isNullOrUndefined(value) {
    return (value == 'undefined' || value == null);
}
//listener on the ng-model='text', waiting for the data to get dirty
$scope.$watch('text', function (newValue, oldValue) {
   if (newValue != oldValue)
   {
       var truthyVal = !(isNullOrUndefined(newValue));
       if (truthyVal) {
           //angular's way of checking validity as well
           //$scope.myForm.text.$valid
           Checker.email({ email:current }).then(
           function(response) {
              model.$setValidity('textErr', response.available);
          }
       }
   }
}, true);
第二种方法(使用ng-change):
<form name="myForm" ng-controller="ExampleController">
    <input type="email" name="input" ng-model="text" ng-change="checkEmail()" required />
</form>
$scope.checkEmail = function(){
    Checker.email({ email:current }).then(
       function(response) {
          model.$setValidity('textErr', response.available);
       }
}

因为您绑定了blur事件,所以验证不会按您想要的方式工作。您必须在该函数运行之前单击该字段。如果您确实希望在用户输入完电子邮件后进行验证,那么您必须绑定某种键事件。

我的建议是绑定到keyup,只有当电子邮件地址看起来是有效的语法时才做服务器端检查。