web-dev-qa-db-ja.com

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

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

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

79
Maarten

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

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

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

それが私にかかったすべてでした。ドキュメントによると、「送信された状態にフォームを設定します。」 here と記載されています。

41
developering

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

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

そして、あなたはあなたのフォームが有効かどうかをチェックすることができます:

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

そして最後に、すべてがよさそうであればルートを変更したいと思います:

$location.path('/somePath');

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

42
Thilak Rao

誰かが後でこれに戻ってきた場合に備えて...上記のどれも役に立たなかった。そこでangularフォーム検証の根底を掘り下げ、特定のフィールドでバリデーターを実行するために呼び出す関数を見つけました。このプロパティは、便宜上$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でない限り、モデルは未定義に設定されます。有効性が有効に変更された場合、モデルは最後に使用可能な有効な$ modelValue、つまり、最後に解析された値またはスコープから設定された最後の値に設定されます。

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

15
chukkwagon

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の使用例と例 をご覧ください。

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

12
user3920706

ええ、angularの方法は、検証を処理することです。これは、モデルが変更されるたびに行われるため、必要なときにのみユーザーに結果を表示するからです。

この場合、エラーをいつ表示するかを決めるには、フラグを設定するだけです: http://plnkr.co/edit/0NNCpQKhbLTYMZaxMQ9l?p=preview

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

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

11
Oliver

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

9
joshnuss

フォームエラーメッセージを表示するためのグローバル関数を次に示します。

 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);
}
3
Namal

Thilakの答えに基づいて、私はこの解決策を思い付くことができました...

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

// 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
Charles Naccio

注:これはハックであることは知っていますが、単純なメカニズムを提供しなかったAngular 1.2以前では便利でした。

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

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

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

angular.forEach($scope.myform.$$controls, function (field) {
    field.$validate();
});
1
stephaneb

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

<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
Mahib

私は このアプローチ がボタンのクリックで検証を処理するのが好きです。

  1. コントローラから何かを呼び出す必要はありませんが、

  2. それはすべてディレクティブで処理されます。

on github

0
Sathish Naga

これを試すことができます:

// 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