Angular:对表单元素

时间:2015-09-09 18:41:56

标签: 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"
           placeholder="Email"
           required/>
    <span class="message" ng-show="emailValidationMessage">{{emailValidationMessage}}</span>
</label>

我想创建一个指令,该指令接受data-live-email-check属性提供的URL,并将电子邮件发送到该URL,验证它是否已存在。

angular.module("App").directive("liveEmailCheck", [function () {
    return {
        restrict: "A",
        scope: {
            ngModel: "="
        },
        link: function (scope, element, attrs) {
            scope.$watch(
                function(){
                    return scope.ngModel
                },
                function(newVal){
                    console.log(newVal);
                }
            );
        }
    }
}]);

我只想在输入上观看模型,并在更新时触发请求。 由于指令是在标签元素上定义的,因此ngModel未正确绑定。我究竟做错了什么?我的监视表达式没有记录任何内容,因为它永远不会触发。

我知道我可以手动抓住输入,但这看起来好像我打破了我感觉如此“束缚”的“角度模式”。令人沮丧的是,似乎有很多方法可以在Angular中完成所有工作,我无法判断我是否正确接近问题。

- 编辑 -

提供我个人将采取的解决方案(出于对“更好”方式的无知),将是以下内容:

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);
                });
        }
    }
}]);

这个工作,但我觉得它“打破了角度规则”。

2 个答案:

答案 0 :(得分:0)

自定义验证的写法如下:

'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的内置验证集中。

答案 1 :(得分:0)

这里需要的是ng-model asyncValidator。这是一个这样的指令的简单实现。

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>

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