3

AngularJS でカスタム ディレクティブを作成しました。ディレクティブは分離されたスコープを使用し、同じ要素で標準の ngModel のバインディングを何らかの形で防ぎます。パスワードの確認フィールド (例では読みやすくするためのテキスト) を作成したいと考えています。

<input type="text" name="one" ng-model="fields.field_one">
<input type="text" validate-match="fields.field_one" name="two" ng-model="field_two">

一致がない場合、私のディレクティブはフィールドを無効にします。

app.directive('validateMatch', function() {
  return {
    require: 'ngModel',
    scope: { matchValue: '=validateMatch' },
    link: function(scope, elm, attr, ctrl) {
      scope.$watch('matchValue', function(value) {
        ctrl.$setValidity('match', 
            ctrl.$viewValue === value
            || !ctrl.$viewValue && !value);
        });

      function validate(value) {
        ctrl.$setValidity('match', value === scope.matchValue);
        return value;
      }
      ctrl.$parsers.push(validate);
      ctrl.$formatters.push(validate);
    }
  }
});

問題は、モデルを変更してそのフィールドの値を変更できないのはなぜですか? 最初のフィールドは問題なく機能します。

詳細とコメント付きのコードについては、プランカーを参照してください。

4

3 に答える 3

3

コメントで述べたように、分離スコープと ng-model はうまく混ざりません。さらに、別のディレクティブ (この場合は ng-model) と対話する必要があるディレクティブ/コンポーネントを作成しようとしているため、ここでは isolate スコープを使用しないでください。

validateMatch ディレクティブは新しいプロパティを作成しないため、ディレクティブは新しいスコープを作成する必要はありません。 $parseを使用して、属性がvalidate-match参照するプロパティの値を取得できます。

app.directive('validateMatch', function($parse) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elm, attr, ctrl) {
      var model = $parse(attr.validateMatch);

      // watch for linked field change (field_one)
      scope.$watch(model, function(value) {
        console.log('linked change:', value, ctrl.$viewValue);
        // set valid if equal or both falsy (empty/undefined/null)
        ctrl.$setValidity('match', 
            ctrl.$viewValue === value
            || !ctrl.$viewValue && !value);
      });

      // validate on parse/format (field_two)
      function validate(value) {
        var otherFieldValue = model(scope);
        console.log('validate:', value, otherFieldValue);
        // set valid if equal
        ctrl.$setValidity('match', value === otherFieldValue);
        return value;
      }

      ctrl.$parsers.push(validate);
      ctrl.$formatters.push(validate);
    }
  };
});

プランカー

于 2013-08-05T13:18:11.343 に答える
1

マークの提案に従って、回避策を作成することができました。

要素に分離スコープが存在する場合、ngModel はそれを参照します。秘訣は、親スコープを内側から見ることです。手動で ngModel を変更する ($parent を先頭に追加する) か、適切なコンパイル関数によってディレクティブ内でこのプロセスを自動化することができます。

これは私がこれをした方法です:

compile: function(element, attrs, transclude) {
    // reference parent scope, because isolated
    // scopes are not looking up by default
    attrs.$set('ngModel', '$parent.'+attrs.ngModel, false);

    return function(scope, elm, attr, ctrl) {
        // link function body there
    }
}

完全な例については、このplunkを見てください。

于 2013-08-04T13:16:02.873 に答える
0

AngularJS ディレクティブについて私が理解していることから、transcludeパラメーターを使用してコントローラーの親スコープにアクセスできます。

于 2013-10-31T00:18:44.567 に答える