【问题标题】:angularjs validators not working when used with another directiveangularjs 验证器在与另一个指令一起使用时不起作用
【发布时间】:2014-12-19 09:43:34
【问题描述】:

我有一个“uniqueCheck”指令,它检查值是否已经存在于列表中,并相应地验证 ngModel。该指令在输入标签上使用时按预期工作,但在呈现输入标签的指令上使用时,结果与预期不符。

指令中的验证器函数被调用,但它不会验证或使输入的 ngModel 无效。
您可以在提供的 plnkr 链接上查看指令的完整代码

Plnkr 链接:plnkr

html如下:

<--! when used with a directive -->
<my-wrapper ng-model="values.abc" unique-check="" list="list" prop="name"> </my-wrapper>

<--! when used on an input tag-->    
 <div ng-form="myform">
     <input type="text" unique-check 
        list="list" prop="name" 
        name="myfield" 
        ng-model="values.pqr"/>
  <span>isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>
</div>

【问题讨论】:

    标签: javascript angularjs validation angularjs-directive angularjs-validation


    【解决方案1】:

    您正在创建 2 个单独的 ngModel 实例,它们都会在输入更改时更新。

    第一个是由&lt;input&gt; 本身创建的,它是分配给“myform”的。这也是my-wrapper中的&lt;span&gt;错误信息绑定的。

    第二个是由my-wrapper 指令创建的 - 这是附加了验证器的那个。

    如果您检查控制台(对于下面的 plnkr)并检查输入更改时验证器输出的值,您可以看到与验证器关联的 ngModelngModel 不一样与表格相关联。但是当输入发生变化时,两者实际上都在更新。

    页面加载后清除控制台,然后在更改第一个输入时检查输出。

    http://plnkr.co/edit/nz6ODOVpn6lJlb055Svs?p=preview


    为什么会这样?

    因为两个ng-model 指令都传递了相同的字符串('values.abc'),然后根据范围对其进行评估以确定它们应该监视和更新哪个对象属性 - 即双向绑定。

    因此,当您更改输入时,您将通过输入 ngModel 实例更改 scope.values.abc 的值。 my-wrapperngModelinstance 获取此更改 - 因为它正在查看相同的对象属性 - 然后验证自身。

    您无法以这种方式解决问题,因为 ngModel 指令需要一个字符串,而不是另一个 ngModelinstance。


    解决方案

    您可以在编译时将属性从my-wrapper 转移到input

    app.directive("myWrapper", function(){
    
        var templateFn = function(element, attrs){
            return '<div ng-form="myform">'+
                       '<input type="text" name="myfield"/>'+
                       '<span>(inside directive) : isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>'
                   '</div>';
        }
    
        return {
            restrict :'E',
            template : templateFn,
            require: 'ngModel',
            scope: true,
            compile: function(element, attrs) {
                var attr;
                angular.forEach(element.find('input'), function(elem) {
                    elem = angular.element(elem)
                    for(attr in attrs.$attr) {
                        elem.attr(attrs.$attr[attr], attrs[attr]);
                    }
                });
    
                for(attr in attrs.$attr) {
                    element.removeAttr(attrs.$attr[attr]);
                }
            }
        }
    });
    

    http://plnkr.co/edit/m2TV4BZKuyHz3JuLjHrY?p=preview

    【讨论】:

    • 用例与上面完全相同:我的包装器指令减少了样板html并将所有角度指令移动到内部输入标签上,知道如何解决这个问题
    • james... 使用你的 plunker 是不同的question of mine
    【解决方案2】:

    不要在 myWrapper 指令中使用范围,它会创建一个单独的变量范围。此外,您需要使用 element.ngModel,而不仅仅是字符串 'ngModel' 作为 ng-model。

    像这样改变你的 myWrapper 指令来工作:

    app.directive("myWrapper", function(){
        var templateFn = function(scope, element, attrs){
        return '<div ng-form="myform">'+
              '<input type="text" name="myfield" ng-model="'+element.ngModel+'"/>'+
              '<span>isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>'
              '</div>';
      }
    
      return {
          restrict :'E',
          template : templateFn,
          //require: 'ngModel',
          //scope: {'ngModel' : '='}
      }
    

    });

    【讨论】:

    • 大声笑,你为什么不赞成我的回答?我的解决方案适用于您的原始问题,我不知道您还需要什么。另外,你说你需要范围,但我刚刚检查了你更新的 plunker,我没有看到范围的任何用法......
    • @JoeSamanek 此解决方案在应用于 plnkr 时似乎不起作用。它显示原始值是重复的,但在输入更改时不会更新。诚然,我可能遗漏了一些东西,因为我认为原始发布的 plnkr 可能有所不同,所以也许它可以解决这个问题? - plnkr.co/edit/ZK4CQfFqxFXgxdAHdFkY?p=preview
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 2013-10-06
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多