2013-09-21 85 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)。 –