Javascript 作用域中的新值。$watch未定义

Javascript 作用域中的新值。$watch未定义,javascript,angularjs,Javascript,Angularjs,我正在尝试创建一个指令来检查输入到文本框中的值的唯一性。但是newVal和oldVal总是在scope.$watch被包装到ctrl.$parsers.push()函数中时未定义 有人知道为什么newVal和oldVal没有定义吗 以下是JSFIDLE: HTML <div ng-app="myApp" ng-controller="TestCtrl"> {{testVar}} <form novalidate> <input type="

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

有人知道为什么newVal和oldVal没有定义吗

以下是JSFIDLE:

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>
要回答您的问题“如何在每次值更改时将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
   });
}

之所以不断获取未定义的值,是因为您没有从解析器函数返回已定义的值

从$parsers的角度文档中:

每当控件 从DOM中读取值。依次调用每个函数,传递 将值传递到下一个。用于将值清理/转换为 以及验证。为了进行验证,解析器应该更新 使用$SETVALITY()的有效性状态,并返回INDEFINED for invalid 价值观

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

以下是我认为您希望实现的内容

以下是该指令的代码:

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

您不应该将
作用域。$watch()
函数放在解析器内部,因为每次执行解析器时(即每次输入更改时),它都会注册一个新的
作用域。$watch()
。感谢您的输入。这已经很有帮助了。您有什么建议吗?每次值更改时,我如何将ngModel的值放入指令中,以便验证它是否已经存在?这会使获取新值变得更好,但您也忘记了从解析器函数返回。这导致实际模型值未定义且始终保持不变。感谢@VermanApeman,我很懒,我只是在对问题的评论中回答了Christopher的问题:“每次值发生变化时,我如何将ngModel的值纳入我的指令中”。感谢您提供完整的答案(+1)。请注意,与下面的答案一样,新值被传递到解析器函数中,因此我们实际上不必使用ctrl.$viewValue。
.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.
            });
        }
    };
});