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

时间:2014-08-04 20:34:32

标签: javascript angularjs validation bind directive

我在'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>'
    };
  });

2 个答案:

答案 0 :(得分:2)

我认为通过制定指令可能会使事情变得复杂,为什么不简单地将控制器添加到控制器中?

注意:如果这些方法中的任何一种方法对您有用,我就不熟悉了,但是我将它们添加为不会绑定到&#34;模糊&#34;事件,而是在MODEL发生变化时触发事件。这是角度设计的目的。我还假设您的Checker正确处理承诺

第一种替代方法(使用$ 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);
       }
}

答案 1 :(得分:0)

由于您对模糊事件具有约束力,因此验证无法按您的方式工作。在该功能可以运行之前,您必须单击该字段。如果您确实希望它在完成键入电子邮件时进行验证,那么您将必须绑定到某种键事件。

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