2013-09-21 98 views
3

我试图创建一个指令来检查输入到文本框中的值的唯一性。但是newVal和oldVal总是未定义为scope。$ watch包含在ctrl。$ parsers.push()函数中。

有人知道为什么newVal和oldVal未定义?

这里是的jsfiddle:

http://jsfiddle.net/charms/v6ttW/7/

HTML

<div ng-app="myApp" ng-controller="TestCtrl"> 
{{testVar}} 
    <form novalidate> 
     <input type="text" name="user.email" ng-model="user.email" email-used="/api/user"/> 
    </form> 
</div> 

Angularjs

angular.module('myApp', []) 
.controller('TestCtrl', ['$scope',function($scope) { 
    $scope.user = {email: 'abc', name: 'myname'}; 
    $scope.testVar = "Test"; 
}]) 
.directive('emailUsed', [function() { 
     return { 
      require: 'ngModel', 
      link: function(scope, elem, attr, ctrl) { 
       console.log("executing"); 
       ctrl.$parsers.push(function() { 
        ctrl.$setValidity('eaCheckingUniqueValue', true); 
        if(ctrl.$valid) { 
         console.log("valid"); 
         scope.oldValues = []; 
         scope.$watch(attr.ngModel, function(newVal, oldVal) { 
          scope.oldValues.push(newVal); 
          console.log("new value is: " + newVal); 
         }); 
         console.log("valid is true"); 
        } else { 
         console.log("valid is false"); 
        } 
       }); 
+3

你不应该把一个'范围$腕表()解析器的内部'功能,因为它会注册一个新的'$范围的手表。 ()'每次解析器执行时(每次输入改变时)。 – rtcherry

+0

感谢您的投入。这已经有很大帮助了。你有什么建议,我怎么会得到ngModel的价值在我的指令每当价值改变,以便我可以验证它是否已经存在? –

回答

2

原因你继续获取未定义的值是因为您没有从解析器函数返回定义的值。

从角文档$解析器:

的函数阵列来执行,作为一个管道,每当控制 从DOM读取值。每个函数被调用,反过来,通过 到下一个值。用于清理/转换值为 以及验证。为了进行验证,解析器应使用$ setValidity()更新 有效性状态,并返回undefined表示无效的 值。

因为在解析器中没有返回语句,所以总是返回undefined(无效值)。

这是我认为你期待实施的working plunker

下面是指令代码:

.directive('emailUsed', function() { 
    return { 
     require: 'ngModel', 
     link: function (scope, elem, attr, ctrl) { 
      scope.oldValues = []; 
      scope.$watch(attr.ngModel, function(newVal, oldVal) { 
       if (angular.isDefined(newVal)) { 
        scope.oldValues.push(newVal); 
       } 
      }); 
      ctrl.$parsers.push(function() { 
       if (ctrl.$viewValue.indexOf('@') !== -1) { 
        ctrl.$setValidity('eaCheckingUniqueValue', true); 
        return ctrl.$viewValue; 
       } 
       ctrl.$setValidity('eaCheckingUniqueValue', false); 
       return undefined; // Model is not valid so return undefined. 
      }); 
     } 
    }; 
}); 
+0

请注意,像下面的答案一样,新值传递给解析器函数,所以我们不必使用ctrl。$ viewValue。 – mortalapeman

1

要回答你的问题“?我将如何得到我的指令ngModel的值每次变化值”,每个语法分析器功能接收新值作为参数:

link: function(scope, elem, attr, ctrl) { 
    console.log("executing"); 
    scope.oldValues = []; 
    ctrl.$parsers.push(function(newVal) { 
     ctrl.$setValidity('eaCheckingUniqueValue', true); 
     if(ctrl.$valid) { 
     console.log("valid"); 
     scope.oldValues.push(newVal); 
     console.log("new value is: " + newVal); 
     } else { 
     console.log("valid is false"); 
     } 
     ... // see mortalapeman's answer for a complete parser implementation 
    }); 
} 

fiddle

+0

那么这会让新值更好一些,但你也忘了从你的解析器函数中返回。这会导致实际模型值不确定,并始终保持这种状态。 – mortalapeman

+0

谢谢@mortalapeman,我很懒,我只是在关于这个问题的评论中解决了克里斯托弗的问题:“如何在每次值改变时获得ngModel对我的指令的价值”。感谢您的完整答案(+1)。 –