AngularJS 自定义表单验证指令在我的模态中不起作用 [英] AngularJS custom form validation directive doesn't work in my modal

查看:27
本文介绍了AngularJS 自定义表单验证指令在我的模态中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

模态和表单中的代码相同

<div class="row"><div nx-validate class="form-group has-feedback col-lg-6 col-md-6 col-xs-12"><label class="control-label">如果足够长,绿色,如果不够则红色</label><input type="text" id="name" class="form-control" ng-model="property.name" required="required" ng-minlength="5"/>(一碰就变色——幸福的脸)

还有我可爱的指令

nitro.directive("nxValidate", function($compile) {返回 {限制:'A',优先级:2000,编译:函数(元素){var 节点 = 元素;while (node && node[0].tagName != 'FORM') {console.log (node[0].tagName)节点 = node.parent();}if (!node) console.error("没有表单节点作为父节点");var formName = node.attr("name");if (!formName) console.error("Form 需要一个 name 属性");var label = element.find("label");var input = element.find("输入");var inputId = input.attr("id")if (!label.attr("for")) {label.attr("for", inputId);}if (!input.attr("name")) {input.attr("name", inputId);}如果(!input.attr(占位符")){input.attr("占位符", 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);返回函数($scope){fn($scope);}}}});

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

解决方案

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

返回函数($scope, element) {fn($scope);$scope.$watch(function(){返回 $scope.modalForm.name.$invalid &&$scope.modalForm.name.$touched;},函数(新值){如果(新值)element.addClass('有错误');别的element.removeClass('有错误');})$scope.$watch(function(){返回 $scope.modalForm.name.$valid &&$scope.modalForm.name.$touched;},函数(新值){如果(新值)element.addClass('已成功');别的element.removeClass('已成功');})}

此处演示

更新

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

代码

编译:函数(元素){//..其他代码将保持原样..element.removeAttr("nx-validate");//var fn = $compile(element);//从编译fn中删除这一行返回函数($scope,元素){//fn($scope);$compile(element)($scope);//在postLink中添加以编译dom以获得绑定工作}}

更新的 Plunkr

I decided to write a custom directive to help me validate my input boxes. The idea is that I add my new fancy nx-validate directive to a bootstrap div.form-group and it'll check whether my <input/> is $dirty or $invalid and apply the .has-success or .has-error class as required.

For some odd reason, my directive works perfectly under normal circumstances, but the added ng-class is completely ignored inside a ui-bootstrap modal.

Identical code in both the modal and the form

<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>        

And my lovely directive

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

        }
    }
});

Check it out on plunker: http://plnkr.co/edit/AjvNi5e6hmXcTgpXgTlH?

解决方案

The simplest way I'd suggest you is you can put those classes by using watch on those fields, this watcher will lie inside the postlink function after compiling a DOM

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

Update

The actual better way of doing this would be instead of compiling element from compile, we need $compile the element from the link function itself. The reason behind the compiling DOM in link fn using $compile is that our ng-class attribute does contain the scope variable which is like myForm.name.$invalid ,so when we $compile the DOM of compile function then they are not evaluating value of myForm.name.$invalid variable because compile don't have access to scope & the would be always undefined or blank. So while compile DOM inside the link would have all the scope values are available that does contain myForm.name.$invalid so after compiling it with directive scope you will get your ng-class directive binding will work.

Code

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

这篇关于AngularJS 自定义表单验证指令在我的模态中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆