Javascript 角度:对表单元素的指令访问

Javascript 角度:对表单元素的指令访问,javascript,angularjs,Javascript,Angularjs,我有一个包含输入的表单标签: <label data-live-email-check="http://www.example-service-uri.com/"> <span class="embedded-label">Email</span> <input ng-model="formData.email" type="email" name="email" plac

我有一个包含输入的表单标签:

<label data-live-email-check="http://www.example-service-uri.com/">
    <span class="embedded-label">Email</span>
    <input ng-model="formData.email"
           type="email"
           name="email"
           placeholder="Email"
           required/>
    <span class="message" ng-show="emailValidationMessage">{{emailValidationMessage}}</span>
</label>
我只想在输入端查看模型,并在模型更新时发出请求。 由于指令是在标签元素上定义的,因此未正确绑定ngModel。我做错了什么?我的watch表达式没有记录任何内容,因为它从不触发

我知道我可以手动抓取输入,但这似乎打破了我感到如此束缚的角度模式。令人沮丧的是,似乎有太多的方法以角度来做每件事,我永远无法判断我是否正确地处理了一个问题

-编辑-

为了提供我个人出于对更好方法的无知而采取的解决方案,我将采取以下措施:

angular.module("App").directive("liveEmailCheck", [function () {
    return {
        restrict: "A",
        require: ["^form"],
        link: function (scope, element, attrs, ctrl) {
            var formCtrl = ctrl[0];
            scope.formEl = formCtrl[element.find("input").attr("name")];


            scope.$watch(function(){return scope.formEl.$valid},  
                function(newVal){
                    console.log(newVal);
                });
        }
    }
}]);

这是可行的,但我觉得它打破了角度规则。

自定义验证是这样编写的:

'use strict';

angular.module('App')
  .directive('liveEmailCheck', function (){

    return {
      require: 'ngModel',
      link: function (scope, elem, attr, ngModel){
        ngModel.$validators.liveEmailCheck= function (value){
         //Your logic here or in a factory
        };
      }
    };
  });
然后在你的HTML上,它就像

<input type="email" live-email-check="liveEmailCheck>

基本上,您将自己的验证添加到angular的内置验证集合中

这里您需要的是ng模型。下面是这样一个指令的简单实现

angular.module("App").directive('asyncEmailValidator', function ($http) {
  return {
    require: 'ngModel',
    link: function (scope, element, attrs, ngModel) {
      var emailValidationUrl = attrs.asyncEmailValidator;
      ngModel.$asyncValidators.emailValidator = function (modelValue, viewValue) {
        var value = modelValue || viewValue;
        // NOTE: don't forget to correctly add the value to the url
        return $http(emailValidationUrl + value).then(function (validationResponse) {
          // NOTE: return rejected promise if validation failed else true
        });

      };
    }
  };
});
如何在您的案例中使用它:

<label>
    <span class="embedded-label">Email</span>
    <input ng-model="formData.email"
           async-email-validator="http://www.example-service-uri.com/"
           type="email"
           name="email"
           placeholder="Email"
           required/>
    <span class="message" ng-show="<FormNameHere>.email.$error.emailValidator">
        {{emailValidationMessage}}
    </span>
</label>

这将是正确的解决方案,因为它是通过angular ng model validation实现的,该验证也考虑了模型的有效性。

但我需要将指令放在外部标签元素上。其他标记需要指令范围,因为像validationMessage这样的东西,以及其他将来添加的东西都需要在指令范围内。您能否坚持提供的标记,并以这种方式提供解决方案?此外,命名是confusign-该指令的目的不是验证输入,而是验证电子邮件是否存在于远程数据源。这引发了另一个问题,我是否需要制定两个指令来实现这一点?这是Angular让我恶心的案例之一。我觉得你应该能够用一段代码来完成这项工作。嗯,好的,我明白你的意思了。是的,我知道这种感觉。指令真是一团糟!在输入中使用ng模型,在指令中用{{formData.email}将其作为表达式计算,然后使用我的自定义验证器,怎么样???只是一种预感…哈哈,是的,似乎这就是一个人必须要做的,对吗?叹气我发誓总有一天我会掌握这个窍门的。无论哪种方式,我都会在弄清楚该怎么做后更新。谢谢你的帮助。你为什么在标签上用它?标签和它的内容是否封装在另一个指令中?是的,它们封装在另一个指令中,但这并不重要,一个人应该能够在没有包装指令的情况下使用它。重要的是emailValidationMessage应该能够根据指令范围进行响应。这是一个误导性的名称,因为这不是为了验证,而是为了检查电子邮件是否存在。您如何使用编辑块中提供的实现来验证电子邮件是否存在?我还不够深入;我要说的是,在这一点上,实际存在性检查是不相关的,因为我还没有到达我能够启动检查的地方!
<label>
    <span class="embedded-label">Email</span>
    <input ng-model="formData.email"
           async-email-validator="http://www.example-service-uri.com/"
           type="email"
           name="email"
           placeholder="Email"
           required/>
    <span class="message" ng-show="<FormNameHere>.email.$error.emailValidator">
        {{emailValidationMessage}}
    </span>
</label>