angularjs验证器与其他指令一起使用时不起作用

时间:2014-12-19 09:43:34

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

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

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

Plnkr Link: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>

2 个答案:

答案 0 :(得分:2)

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

第一个是由<input>本身创建的,这是分配给'myform'的那个。这也是<span>中的my-wrapper错误消息也绑定的那个。

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

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

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

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


为什么会这样?

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

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

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


解决方案

您可以在编译时将属性从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

答案 1 :(得分:0)

不要在myWrapper指令中使用scope,它会创建一个单独的变量范围。此外,您需要使用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' : '='}
  }

});