AngularForm送信のすべてのフィールドの検証をトリガーします


81

私はこの方法を使用しています:http//plnkr.co/edit/A6gvyoXbBd2kfToPmiiA?p = previewはぼかしのフィールドのみを検証します。これは正常に機能しますが、ユーザーが[送信]ボタン(実際の送信ではなく、関数へのdata-ng-click呼び出し)をクリックしたときに、それらを検証します(したがって、これらのフィールドのエラーがあれば表示します)。

そのボタンをクリックしたときに、すべてのフィールドで検証を再度トリガーする方法はありますか?


プランカーのボタンはどこにありますか?
callmekatootie 2013年

申し訳ありませんが、プランカーは私のコードのベースになっています。私は自分の状況にもっと似せるためにフォークを作りました:plnkr.co/edit/VfvCSmjlzpIgUH4go2Jn?p
Maarten

回答:


44

私のために働いたのは$setSubmitted、バージョン1.3.20のAngularドキュメントに最初に表示される関数を使用することでした。

検証をトリガーしたいクリックイベントで、次のことを行いました。

vm.triggerSubmit = function() {
    vm.homeForm.$setSubmitted();
    ...
}

それが私にとって必要なすべてでした。ドキュメントによると、「フォームを送信された状態に設定します」。ここで言及されています


4
これは、使用している場合は機能せずng-messages$ error && $ dirtyの場合にのみ表示されます。
JobaDiniz 2016年

@JobaDiniz $ setDirty関数を試しましたか?それは私の答えからのリンクにも記載されています:code.angularjs.org/1.3.20/docs/api/ng/type/form.FormControllerお役に立てば幸い です!
開発

2
それは機能しませんform...私はすべての入力をループし$setDirty()てそれらを呼び出す必要がありました。
JobaDiniz 2016年

43

答えるには少し遅すぎますが、あなたがする必要があるのは、すべてのフォームを強制的に汚すだけです。次のスニペットを見てください。

angular.forEach($scope.myForm.$error.required, function(field) {
    field.$setDirty();
});

次に、以下を使用してフォームが有効かどうかを確認できます。

if($scope.myForm.$valid) {
    //Do something
}   

そして最後に、すべてが良さそうな場合は、ルートを変更することをお勧めします。

$location.path('/somePath');

編集:送信イベントがトリガーされるまで、フォームはスコープに登録されません。ng-submitディレクティブを使用して関数を呼び出し、上記をその関数でラップするだけで、機能するはずです。


1
プログラムでng-submitディレクティブをトリガーする例を提供できますか?
chovy 2016

@chovyng-submitは、関数を送信イベントにバインドするだけです。その関数を呼び出すだけではどうでしょうか。
Thilak Rao 2016

ディレクティブの外側のフォームフィールドを更新するディレクティブがフォームに埋め込まれています...検証するフォームフィールドをクリックしてぼかしない限り、バリデーターは適用されません。
chovy 2016

私はそれに渡されるフォームオブジェクトを持っていません
chovy 2016

@chovy私はあなたを正しく理解していません。しかし、私はあなたを助けようとします。デバウンスで検証を試みましたか?
Thilak Rao 2016

17

誰かが後でこれに戻ってきた場合に備えて...上記のどれも私にはうまくいきませんでした。そこで、角度フォーム検証の本質を掘り下げて、特定のフィールドでバリデーターを実行するためにそれらが呼び出す関数を見つけました。このプロパティは便利にと呼ばれ$validateます。

名前付きフォームがある場合は、myFormプログラムで呼び出しmyForm.my_field.$validate()てフィールド検証を実行できます。例えば:

<div ng-form name="myForm">
    <input required name="my_field" type="text" ng-blur="myForm.my_field.$validate()">
</div>

呼び出すことに注意してください $validateはモデルに影響を与えるてください。ngModelCtrl。$ validateのAngularドキュメントから:

登録された各バリデーターを実行します(最初に同期バリデーター、次に非同期バリデーター)。有効性が無効に変更された場合、ngModelOptions.allowInvalidがtrueでない限り、モデルは未定義に設定されます。有効性がvalidに変更されると、モデルは最後に使用可能な有効な$ modelValue、つまり最後に解析された値またはスコープから設定された最後の値に設定されます。

したがって、無効なモデル値を使用して何かを行うことを計画している場合(そのように通知するメッセージをポップするなど)、モデルに対してallowInvalidがに設定さtrueれていることを確認する必要があり ます。


存在しない場合の非常に驚くべき「モデルが未定義になる」結果に関する詳細な説明は、allowInvalidここで読むことができます:github.com/angular/angular.js/issues/10035
pestophagous 2010

12

Angular-Validatorを使用して、必要なことを実行できます。使い方はばかげています。

そうなる:

  • オン$dirtyまたはオンのフィールドのみを検証しますsubmit
  • フォームが無効な場合は送信されないようにする
  • フィールドがである$dirtyか、フォームが送信された後にカスタムエラーメッセージを表示する

デモを見る

<form angular-validator 
       angular-validator-submit="myFunction(myBeautifulForm)"
       name="myBeautifulForm">
       <!-- form fields here -->
    <button type="submit">Submit</button>
</form>

フィールドが合格しない場合、validatorユーザーはフォームを送信できません。

詳細については、角度バリデーターの使用例と例を確認してください。

免責事項:私はAngular-Validatorの作者です


11

まあ、角度のある方法は、検証を処理させることです-それはすべてのモデル変更で行うので-そしてあなたが望むときだけユーザーに結果を表示します。

この場合、エラーを表示するタイミングを決定するには、フラグを設定する必要があります:http//plnkr.co/edit/0NNCpQKhbLTYMZaxMQ9l?p = preview

私の知る限り、より高度なフォーム制御を可能にするためにAngularに提出された問題があります。解決されていないので、既存のすべての検証方法を再発明する代わりにこれを使用します。

編集:しかし、あなたが途中で主張するならば、これは提出する前に検証されたあなたの修正されたフィドルです。http://plnkr.co/edit/Xfr7X6JXPhY9lFL3hnOw?p=preview コントローラーは、ボタンがクリックされたときにイベントをブロードキャストし、ディレクティブは検証マジックを実行します。


これはこの例では機能しますが、私の場合のように(ただし、そのplunkr..sorry!ではありません)、その電子メールのような複数のディレクティブがある場合はどうなりますか。どういうわけか、ディレクティブから別の検証クラスに検証を移動してから、このフォームのすべての検証メソッドを呼び出す必要がありますか、それともすべてのディレクティブに対して別の方法で検証をトリガーできますか?検証はブラーによってトリガーされるため、コードからブラーをトリガーすることもありますが、それは恐ろしいことのようです。
マールテン

ああ、私はその問題について知っています。残念ながら、まだベータ版ではなく、私が話しているワークフローは、この会社に必須のワークフローです
Maarten 2013年

ブロードキャストされたイベントは、すべてのディレクティブがコントローラーのスコープ内にあるため、すべてのディレクティブで$ onコールバックをトリガーします。
オリバー

ああ..その部分を本当に理解していませんでした。ありがとう!
マールテン2013年

1
イベントをブロードキャストするときに、パラメーターを渡すことができます。$ scope。$ broadcast( 'startValidations'、param1、param2); リッスンは変更されません:scope。$ on( 'startValidations'、validateMe); そして、コールバックでfn:function validateMe(event、param1、param2){}ドキュメントを参照してください:docs.angularjs.org/api/ng.$ro​​otScope.Scope#$broadcast
Oliver

9

1つのアプローチは、すべての属性を強制的にダーティにすることです。各コントローラーでそれを行うことができますが、非常に面倒になります。一般的な解決策がある方がよいでしょう。

私が考えることができる最も簡単な方法は、ディレクティブを使用することでした

  • フォーム送信属性を処理します
  • すべてのフォームフィールドを反復処理し、元のフィールドをダーティとしてマークします
  • 送信関数を呼び出す前に、フォームが有効かどうかを確認します

これがディレクティブです

myModule.directive('submit', function() {
  return {
    restrict: 'A',
    link: function(scope, formElement, attrs) {
      var form;
      form = scope[attrs.name];
      return formElement.bind('submit', function() {
        angular.forEach(form, function(field, name) {
          if (typeof name === 'string' && !name.match('^[\$]')) {
            if (field.$pristine) {
              return field.$setViewValue(field.$value);
            }
          }
        });
        if (form.$valid) {
          return scope.$apply(attrs.submit);
        }
      });
    }
  };
});

次に、フォームのhtmlを更新します。例:

 <form ng-submit='justDoIt()'>

になります:

 <form name='myForm' novalidate submit='justDoIt()'>

ここで完全な例を参照してください:http//plunker.co/edit/QVbisEK2WEbORTAWL7Gu?p = preview


4

これは、フォームのエラーメッセージを表示するための私のグローバル関数です。

 function show_validation_erros(form_error_object) {
        angular.forEach(form_error_object, function (objArrayFields, errorName) {
            angular.forEach(objArrayFields, function (objArrayField, key) {
                objArrayField.$setDirty();
            });
        });
    };

そして、私のどのコントローラーでも、

if ($scope.form_add_sale.$invalid) { 
    $scope.global.show_validation_erros($scope.form_add_sale.$error);
}

1
これは質問に答えません。
Rafael Herscovici 2017年

私は答えを変えました。今すぐ確認してください
ナマル2017年

2

ティラックの答えに基づいて、私はこの解決策を思いつくことができました...

フォームフィールドには、フィールドが無効な場合にのみ検証メッセージが表示され、ユーザーが触れたため、ボタンによってトリガーされるこのコードを使用して、無効なフィールドを表示することができました。

// Show/trigger any validation errors for this step
angular.forEach(vm.rfiForm.stepTwo.$error, function(error) {
  angular.forEach(error, function(field) {
    field.$setTouched();
  });
});
// Prevent user from going to next step if current step is invalid
if (!vm.rfiForm.stepTwo.$valid) {
  isValid = false;
}
<!-- form field -->
<div class="form-group" ng-class="{ 'has-error': rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched && rfi.rfiForm.stepTwo.Parent_Suffix__c.$invalid }">

  <!-- field label -->
  <label class="control-label">Suffix</label>
  <!-- end field label -->
  <!-- field input -->
  <select name="Parent_Suffix__c" class="form-control"
          ng-options="item.value as item.label for item in rfi.contact.Parent_Suffixes"
          ng-model="rfi.contact.Parent_Suffix__c" />
  <!-- end field input -->
  <!-- field help -->
  <span class="help-block" ng-messages="rfi.rfiForm.stepTwo.Parent_Suffix__c.$error" ng-show="rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched">
    <span ng-message="required">this field is required</span>
  </span>  
  <!-- end field help -->
</div>
<!-- end form field -->


2

注:これがハックであることは知っていますが、単純なメカニズムを提供していなかったAngular1.2以前では役に立ちました。

検証は変更イベントで開始されるため、プログラムで値を変更するなどのいくつかのことはそれをトリガーしません。ただし、変更イベントをトリガーすると、検証がトリガーされます。たとえば、jQueryの場合:

$('#formField1, #formField2').trigger('change');

このアプローチは簡単です。さらに、Angularの古い(すべての)バージョンで動作するという利点があります。
Paul LeBeau 2016

3
ではありませんangular way
Rafael Herscovici 2017年


0

あなたはこれを試すことができます:

// The controller

$scope.submitForm = function(form){
   		//Force the field validation
   		angular.forEach(form, function(obj){
   			if(angular.isObject(obj) && angular.isDefined(obj.$setDirty))
   			{ 
   				obj.$setDirty();
   			}
   		})
        
        if (form.$valid){
		
			$scope.myResource.$save(function(data){
		     	//....
			});
		}
}
<!-- FORM -->

  <form name="myForm"  role="form" novalidate="novalidate">
<!-- FORM GROUP to field 1 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field1.$invalid && myForm.field1.$dirty }">
      <label for="field1">My field 1</label>
        <span class="nullable"> 
        <select name="field1" ng-model="myresource.field1" ng-options="list.id as list.name for list in listofall"
          class="form-control input-sm" required>
            <option value="">Select One</option>
        </select>
        </span>
        <div ng-if="myForm.field1.$dirty" ng-messages="myForm.field1.$error" ng-messages-include="mymessages"></div>
  </div>
    
<!-- FORM GROUP to field 2 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field2.$invalid && myForm.field2.$dirty }">
    <label class="control-label labelsmall" for="field2">field2</label> 
      <input name="field2" min="1" placeholder="" ng-model="myresource.field2" type="number" 
      class="form-control input-sm" required>
    <div ng-if="myForm.field2.$dirty" ng-messages="myForm.field2.$error" ng-messages-include="mymessages"></div>
  </div>

  </form>

<!-- ... -->
<button type="submit" ng-click="submitForm(myForm)">Send</button>


0

私はそれを機能させるために次のことをしました。

<form name="form" name="plantRegistrationForm">
  <div ng-class="{ 'has-error': (form.$submitted || form.headerName.$touched) && form.headerName.$invalid }">
    <div class="col-md-3">
      <div class="label-color">HEADER NAME 
        <span class="red"><strong>*</strong></span></div>
    </div>
    <div class="col-md-9">
      <input type="text" name="headerName" id="headerName" 
             ng-model="header.headerName" 
             maxlength="100" 
             class="form-control" required>
      <div ng-show="form.$submitted || form.headerName.$touched">
        <span ng-show="form.headerName.$invalid" 
              class="label-color validation-message">Header Name is required</span>
      </div>
    </div>
  </div>

  <button ng-click="addHeader(form, header)" 
          type="button" 
          class="btn btn-default pull-right">Add Header
  </button>

</form>

あなたのコントローラーであなたはすることができます;

addHeader(form, header){
        let self = this;
        form.$submitted = true;
        ... 
    }

いくつかのCSSも必要です。

.label-color {
            color: $gray-color;
        }
.has-error {
       .label-color {
            color: rgb(221, 25, 29);
        }
        .select2-choice.ui-select-match.select2-default {
            border-color: #e84e40;
        }
    }
.validation-message {
       font-size: 0.875em;
    }
    .max-width {
        width: 100%;
        min-width: 100%;
    }

0

必要なときにフォームのすべてのフィールドを検証するために、次のように$$コントロールの各フィールドで検証を行います。

angular.forEach($scope.myform.$$controls, function (field) {
    field.$validate();
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.