AngularJS 自定义表单验证指令在我的模式中不起作用

Posted

技术标签:

【中文标题】AngularJS 自定义表单验证指令在我的模式中不起作用【英文标题】:AngularJS custom form validation directive doesn't work in my modal 【发布时间】:2015-09-12 17:34:01 【问题描述】:

我决定编写一个自定义指令来帮助我验证我的输入框。这个想法是我将我的新花哨nx-validate 指令添加到引导程序div.form-group,它会检查我的<input/>$dirty 还是$invalid,并根据需要应用.has-success.has-error 类.

出于某种奇怪的原因,我的指令在正常情况下完美运行,但添加的 ng-class 在 ui-bootstrap 模式中被完全忽略。

模态和表单中的相同代码

<form name="mainForm">
  <div class="row">
      <div nx-validate class="form-group has-feedback col-lg-6 col-md-6 col-xs-12">
          <label class="control-label">Green if long enough, red if not</label>
          <input type="text" id="name" class="form-control" ng-model="property.name" required="required" ng-minlength="5"/>
          (once touched I do change colour - happy face)
      </div>
  </div>        

还有我可爱的指令

nitro.directive("nxValidate", function($compile) 
    return 
        restrict: 'A',
        priority: 2000,
        compile: function(element) 

            var node = element;
            while (node && node[0].tagName != 'FORM') 
                console.log (node[0].tagName)
                node = node.parent();
            
            if (!node) console.error("No form node as parent");
            var formName = node.attr("name");
            if (!formName) console.error("Form needs a name attribute");


            var label = element.find("label");
            var input = element.find("input");
            var inputId = input.attr("id")

            if (!label.attr("for")) 
                label.attr("for", inputId);
            

            if (!input.attr("name")) 
                input.attr("name", inputId);
            

            if (!input.attr("placeholder")) 
                input.attr("placeholder", label.html());
            

            element.attr("ng-class", "'has-error' : " + formName + "." + inputId + ".$invalid && " + formName + "." + inputId + ".$touched, 'has-success' : " + formName + "." + inputId + ".$valid && " + formName + "." + inputId + ".$touched");
            element.removeAttr("nx-validate");

            var fn = $compile(element);

            return function($scope) 
                fn($scope);
            

        
    
);

在 plunker 上查看:http://plnkr.co/edit/AjvNi5e6hmXcTgpXgTlH?

【问题讨论】:

将您的按钮放入表单中。当我在 plunker 示例中这样做时对我有用。 【参考方案1】:

我建议您的最简单方法是您可以通过在这些字段上使用 watch 来放置这些类,这个 watcher 将在编译 DOM 后位于 postlink 函数中

return function($scope, element) 
    fn($scope);

    $scope.$watch(function()
      return $scope.modalForm.name.$invalid && $scope.modalForm.name.$touched;
    , function(newVal)
      if(newVal)
        element.addClass('has-error');
      else
        element.removeClass('has-error');
    )

    $scope.$watch(function()
      return $scope.modalForm.name.$valid && $scope.modalForm.name.$touched;
    , function(newVal)
      if(newVal)
        element.addClass('has-success');
      else
        element.removeClass('has-success');
    )

Demo Here

更新

实际更好的方法不是从 compile 编译元素,我们需要 $compile 来自 link 函数本身的元素。使用 $compile 在链接 fn 中编译 DOM 背后的原因是我们的 ng-class 属性确实包含类似于 myForm.name.$invalid 的范围变量,所以当我们 $compile 编译函数的 DOM 时,它们不会评估myForm.name.$invalid 变量,因为 compile 无权访问作用域,并且始终为 undefinedblank。因此,虽然在 link 内编译 DOM 时,所有包含 myForm.name.$invalid 的范围值都可用,因此在使用指令范围编译后,您将获得 ng-class 指令绑定。

代码

compile: function(element) 
    //..other code will be as is..

    element.removeAttr("nx-validate");
      //var fn = $compile(element); //remove this line from compile fn
      return function($scope, element) 
         //fn($scope);
         $compile(element)($scope); //added in postLink to compile dom to get binding working
      
 

Updated Plunkr

【讨论】:

感谢您的回答。您能否向我解释为什么我的示例默认情况下不起作用。除了想要解决这个问题——我相信你的回答会,我想了解为什么我首先会遇到这个问题,并能够避免它在未来发生。是因为模态内容是动态的,而我的指令有错误的优先级或在错误的时间编译,还是你认为这是一个范围问题? @Spider 很抱歉回复晚了..看看我更新的答案。现在应该可以工作了..我认为这是因为ng-class而导致的编译问题 @Spider 你看答案了吗? 太棒了。谢谢你。能否请您指出我可以研究具体细节的资源,以便我能够正确理解这一点? @Spider 不,没有任何官方文件可以阅读此内容..我希望您阅读 SO 帖子,这将帮助您更清楚地了解相同的概念..

以上是关于AngularJS 自定义表单验证指令在我的模式中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS无法将表单输入输入指令

AngularJS中使用的表单验证

(译) 在AngularJS中使用的表单验证功能

在AngularJS中删除输入值时如何再次验证表单

怎么消除angular的表单验证

通过使用 AngularJS 的自定义登录进行 Spring Security 身份验证