3

テキスト ボックスに入力された値の一意性をチェックするディレクティブを作成しようとしています。しかし、scope.$watch が ctrl.$parsers.push() 関数にラップされると、newVal と oldVal は常に未定義になります。

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");
                    }
                });
4

2 に答える 2

2

未定義の値を取得し続ける理由は、パーサー関数から定義済みの値を返していないためです。

$parsers の角度ドキュメントから:

コントロールが DOM から値を読み取るたびに、パイプラインとして実行する関数の配列。各関数が順番に呼び出され、値が次の関数に渡されます。値のサニタイズ/変換と検証に使用されます。検証のために、パーサーは $setValidity() を使用して有効性の状態を更新し、無効な値に対して undefined を返す必要があります。

パーサーに 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.
            });
        }
    };
});
于 2013-09-21T21:53:29.870 に答える
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

于 2013-09-21T21:51:33.457 に答える