FormベースAngularフォームデータ検証

6512 ワード

最近の火のぼろぼろなAngularに薪を添えて、Angularを使ってデータ検査を行った経験を共有します.そもそもフロントエンドデータの検証の方式は数千万であり、本質的には検証表示の方式と時間及び検証トリガ点の違いである.
Angularのデータに対する検証は、基本的にHTML 5のFormフォームの特性に依存する、フォームラベルの検証項目を定義すればよい.
input検証オプション
     1. 必須
<input type='text' name='cityName' required>

     2. 最小長さと最大長さの制限
<input type='text' name='cityName' ng-minlength='5' ng-maxlength='10'>

     3. 数字、メール、URLアドレス制限
<input type='number' name='cityName'> <input type='email' name='cityName'> <input type='url' name='cityName'>

     4. 正規一致
<input type='text' name='cityName' ng-pattern='[0-9]'>

     5. スペースを削除(Angular)
<input type='text' name='cityName' ng-trim=true>

     6. カスタム検証
具体的な業務に従って、データ検証のルールを定義する.通常directiveを1つ作成することができる再利用できない検査であればcontrollerに書いてもよい.この方面のあなたの内容を少し厚く言って、いくつかの敷物が必要です.
Angularプロパティ
Angularはフォームコントロールのためにいくつかの属性を定義、それらの状態を表すために使用され、これらの状態によってフォームおよびそのコントロールに対して簡単にいくつかの操作を行うことができる.現在、Angularが提供するフォームの属性は多くありませんが、最新のbeta版では新しい属性のサポートが徐々に増加していることがわかります.これらの特性は自分で類似の機能をシミュレートすることもできます.
    1. $义齿
formName.inputName.$pristine    //          ,     true
formName.inputName.$dirty       //           true

    2. $validと$invalid
formName.inputName.$valid        //           ,    true
formName.inputName.$invalid      //            ,     true

    3. $error
formName.inputName.$error      //          ,      true, $valid                 ,  formName.inputName.$error.maxlength

Angular高度検査特性
場合によっては、個別のフォーム検証は必要を満たすことができず、2つのデータを関連付けるなどの特殊な検証がある可能性がある.通常、このような検査は多重化可能である、すなわちdirectiveが必要である.作成したカスタムチェックのdirectiveは複雑ではなく、まずいくつかのAngularが提供する属性とインタフェースを理解する必要がある.
    1. $setValidity()
この方法は、フォームコントロールの$validおよび$invalidを人為的に設定することができ、すなわち、フォームコントロールが検証に合格するかどうかの状態を変更することができる.同様に$setDirty()と$setPristine()がある.
ngModel.$setValidity('max-custom', true);    //                      , ngModel   directive   link       ,$setValidity               ,     true       , false      

    2. $parsers
この属性は少し抽象的に解釈され、ngModelの値が変化するとAngularは$setView Value(value)を自分で呼び出し、ngModelの$parsers配列の得関数が1つずつ呼び出され、$parsers[0]のメソッドが呼び出されると実行結果が$parsersに渡される[1].これらの関数は、ngModelの値を変換するか、$setValidity()でフォームの正当性を設定することができる.
したがって、何か特別な検証を実現するには、$parsersにfunctionを挿入し、検証チェーンで呼び出すことができ、データモデルの更新を望まない場合は、$parsersの関数戻り値をundefinedに戻すことができる.
.directive('maxMax', function(){
  return {
    require: 'ngModel',
    restrict: 'A',
    link: function($scope, iElm, iAttrs, ngModel) {
      if(!ngModel) return;
      ngModel.$parsers.unshift(function(viewValue){
        var num = parseInt(viewValue);
        if(num>=0 && num<99){
          ngModel.$setValidity('maxMax',true);
          return viewValue;
        }else{
          ngModel.$setValidity('maxMax',false);
          return undefined;
        }
      });
    }
  };
})

    3. $formatters
$parsersがデータモデルが変化するときの1番の加工ラインである場合、$formattersは2番の流水ラインであり、$parsersで関数処理を行った後、いくつかの特殊なフォーマットを行うことができる.使用方法は$parsersと極めて類似しており、例を挙げない.
カスタム検証directive
比較的一般的な検査は2種類あり、1つは焦点を失った時に検査を行うdirectiveであり、もう1つは提出をクリックしてから検査を開始する.
(1)フォーカスを失った場合のチェック情報の表示
.directive('ngFocus', function(){
  return {
    require: 'ngModel',
    restrict: 'A',
    link: function($scope, iElm, iAttrs, ngModel) {
      if(!ngModel) return;
      ngModel.$focused = false;
      iElm.bind('focus',function(evt){
        iElm.addClass('focus-class');
        $scope.$apply(function(){
          ngModel.$focused = true;
        });
      }).bind('blur',function(evt){
        iElm.removeClass('focus-class');
        $scope.$apply(function(){
          ngModel.$focused = false;
        });
      })
    }
  };
})

フォームのエラーメッセージ表示の条件にformNameを付ける.inputName.$focused==trueでよい.
(2)submitボタンをクリックしてチェックをオンにする
 /**
   *     
   * form    validation-form   ,          validation
   */
  .directive('validationForm', function(){
    return {
      restrict: 'A',
      link: function($scope, iElm, iAttrs, controller) {
        $scope.submitted = false;
        $scope.flag = false;
        var controls = iElm.find('input[validation]','select[validation]');
        iElm.find('button[type="submit"]').on('click',function(e){
          addSubmitEvent(e);
        });
        iElm.parents('.container').find('#'+iAttrs.validationForm).on('click',function(e){
          addSubmitEvent(e);
        });
        var addSubmitEvent = function(e){
          $scope.submitted = true;
          $.each(controls,function(i,c){
            validClass($scope[iAttrs.name][$(c).attr('name')].$valid,$(c));
            if(!$scope.flag){
              setWatch($(c));
            }
          })
          $scope.flag = true;
        }
        var validClass = function(nv,control){
          if(nv && $scope.submitted){
            control.parent().addClass('state-success');
            control.parent().removeClass('state-error');
            control.parent().next('.note').first().addClass('note-success');
            control.parent().next('.note').first().removeClass('note-error');
          }else if(!nv && $scope.submitted){
            control.parent().addClass('state-error');
            control.parent().removeClass('state-success');
            control.parent().next('.note').first().addClass('note-error');
            control.parent().next('.note').first().removeClass('note-success');
          }
        }
        //          
        var setWatch = function(control){
          var cValid = iAttrs.name+"."+control.attr('name')+".$valid";
          $scope.$watch(cValid,function(nv,ov){
            validClass(nv,control);
          })
        }
      }
    };
  });

Angularは1.3バージョン以降にsubmittedという属性をサポートする予定なので、今は自分でシミュレーションして以下を実現する必要があります.上記の実現は実はさらに進むことができますが、しばらくは十分で変更されていません.興味のある人は自分でもっと規則に合ったものを書くことができます.