2016-11-11 3 views
0

フォーム要素ラッパーとして機能する 'wrapper'指示文を作成しました。 1つまたは複数の入力をこのディレクティブの中にラップすることができます。ng-formに触れるかどうかを確認する方法

ディレクティブ自体にng-formというディレクティブが含まれているため、エラーがあり、(ng-model)入力が無効な場合は、各インスタンスを確認できます。

  • フォームが送信され
  • OR:

    • つ以上の入力が$無効
    • としている:私のラッパーテンプレートで

      は私がするとき 'エラー' クラスを追加します
    • 1つまたは複数の入力が$接触された

これは私の現在の(剥奪)のラッパーディレクティブです:

export class FormElementWrapper { 
    public transclude = true; 

    public template = ` 
     <div ng-form="formElementWrapper" 
      ng-class="{'has-error': showError }" ng-transclude> 
     </div> 
    `; 

    public link = (scope, element, attrs) => { 
     // custom keep track of touched 
     var touched = false; 

     var isSubmitted = function(): boolean { 
      var form: any = scope.formElementWrapper; 
      return form.$$parentForm.$submitted; 
     }; 

     scope.$watch(() => { 
      // show error when: 
      // - one ore more inputs are invalid 
      // - AND 
      // -- form is touched 
      // -- OR 
      // -- parent form is submitted 
      var submitted = isSubmitted(); 
      return scope.formElementWrapper.$invalid && (touched || submitted); 
     }, (val) => { 
      scope.showError = val; 
     }); 

     // override $setPristine to reset the custom touched property 
     var origPristine = scope.formElementWrapper.$setPristine; 
     scope.formElementWrapper.$setPristine =() => { 
      touched = false; 
      origPristine(); 
     } 

     // bind to blur events of all inputs 
     element.on("blur", ":input",() => { 
      touched = true; 
     }); 
    } 
} 

質問:1つの以上の要素が$をしている場合、私は知ることができますどのように触れましたか? ngFormControllerにはそのプロパティはありません。現在私は入力のblurイベントにバインドしていますが、ng-modelを使用する他のディレクティブは入力そのものである必要はないと思います。

答えて

2

あなたは基本的に手の届かないところの否定を否定することができます。それは$pristineです。したがって、if(!form.$pristine)を使用して確認することができます。フォームがタッチされたことを意味します。

form.FormController docsによれば、$pristineTrueです。ユーザーがまだフォームとやりとりしていない場合。

ただし、NgModelController.$touchedをFormControllerに拡張する場合は、要素がbluredになったときにフォームに$touched = trueを追加するだけです。 ngModelと同時にディレクティブを使用して、blurイベントによって要素がトリガーされると、FormController.$touchedの値が変更されます。

次の例は、このソリューションを実装しています。

angular.module('app', []) 
 
    .directive('ngModel', function() { 
 
    return { 
 
     restrict: 'A', 
 
     require: ['^?form'], 
 
     priority: 1000, 
 
     link: function(scope, elem, attr, ctrls) { 
 
     var ngFormCtrl = ctrls[0]; 
 

 
     if (ngFormCtrl) { 
 
      elem.on('blur', function onBlurEvent() { 
 
      scope.$apply(function() { 
 
       ngFormCtrl.$touched = true; 
 
       elem.off('blur', onBlurEvent); 
 
      }); 
 
      }); 
 
     } 
 
     } 
 
    }; 
 
    }) 
 
    .controller('myController', function($rootScope) { 
 

 
    var $ctrl = this; 
 

 
    $ctrl.model = { 
 
     name: 'lenny', 
 
     age: 23 
 
    }; 
 
    }); 
 

 
angular.element(document).ready(function() { 
 
    angular.bootstrap(document, ['app']); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.js"></script> 
 
<div ng-controller="myController as $ctrl"> 
 
    <form name="$ctrl.myForm" novalidate> 
 
    <label>Name : 
 
     <input name="test1" ng-model="$ctrl.model.name"> 
 
    </label> 
 
    <label>age : 
 
     <input name="test2" ng-model="$ctrl.model.age"> 
 
    </label> 
 

 
    <label>{{ $ctrl.myForm.$touched ? 'Touched' : 'Untouched'}}</label> 
 
    </form> 
 
</div>

+0

あなたの答えをいただき、ありがとうございます。これは 'フォームとの対話 'として文書化されているので、これを試しましたが、' $ tuched'ではなく '$ dirty'フラグの反対に動作するようです。 – devqon

+0

はい、フォームオブジェクト(モデル) DOM入力要素ではありません。 –

+0

@devqon実際には、ngModelController touchedがngFormControllerに組み込まれていないため、必要に応じて実装する必要があります(途中で難しくありません)。 –

関連する問題