24

私はAngularフォームを持っています。ng-patternフィールドは属性を使用して検証されます。リセットボタンもあります。私は次のようにイベントを処理するためにUi.Utils Event Binderresetを使用しています:

<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()">
  <div>
    <label>
      Area Code
      <input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/">
    </label>

    <div ng-messages="searchForm.areaCode.$error">
      <div class="error" ng-message="pattern">The area code must be three digits</div>
    </div>
  </div>

  <div>
    <label>
      Phone Number
      <input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/">
    </label>

    <div ng-messages="searchForm.phoneNumber.$error">
      <div class="error" ng-message="pattern">The phone number must be seven digits</div>
    </div>
  </div>

  <br>
  <div>
    <button type="reset">Reset</button>
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button>
  </div>
</form>

ご覧のとおり、フォームがリセットされると、 のresetメソッドが呼び出され$scopeます。コントローラ全体は次のようになります。

angular.module('app').controller('mainController', function($scope) {
    $scope.resetCount = 0;

    $scope.reset = function(form) {
        form.$setPristine();
        form.$setUntouched();
        $scope.resetCount++;
    };

    $scope.search = function() {
        alert('Searching');
    };
});

ここスタック オーバーフローに関する別の質問からのアドバイスに従って、電話form.$setPristine()しています。カウンターを追加した唯一の理由は、コードが呼び出されていることを証明することでした (それはそうです)。form.$setUntouched

問題は、フォームをリセットした後でも、検証メッセージが消えないことです。Plunkerで完全なコードを見ることができます。エラーが消えないことを示すスクリーンショットを次に示します。

検証エラー

4

10 に答える 10

22

@Brett からのコメントから始めて、それに基づいて構築しました。実際には複数のフォームがあり、各フォームには多くのフィールドがあります (表示されている 2 つだけではありません)。だから私は一般的な解決策が欲しかった。

formAngularオブジェクトには、各コントロール (input、select、textarea など) のプロパティと、他のいくつかの Angular プロパティがあることに気付きました。ただし、各 Angular プロパティはドル記号 ( ) で始まります$。だから私はこれをやった(他のプログラマーの利益のためのコメントを含む):

$scope.reset = function(form) {
    // Each control (input, select, textarea, etc) gets added as a property of the form.
    // The form has other built-in properties as well. However it's easy to filter those out,
    // because the Angular team has chosen to prefix each one with a dollar sign.
    // So, we just avoid those properties that begin with a dollar sign.
    let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0);

    // Set each control back to undefined. This is the only way to clear validation messages.
    // Calling `form.$setPristine()` won't do it (even though you wish it would).
    for (let name of controlNames) {
        let control = form[name];
        control.$setViewValue(undefined);
    }

    form.$setPristine();
    form.$setUntouched();
};
于 2015-06-23T20:20:14.967 に答える
7
      $scope.search = {areaCode: xxxx, phoneNumber: yyyy}

フォーム内のすべてのモデルを上記のように 1 か所で構成すると、次のようにクリアできます。

      $scope.search = angular.copy({});

その後、検証をリセットするためにこれを呼び出すことができます:

      $scope.search_form.$setPristine();
      $scope.search_form.$setUntouched();
      $scope.search_form.$rollbackViewValue();
于 2016-08-07T08:10:45.847 に答える
5

検証フラグを追加して、その値に応じてエラーを表示または非表示にすることができng-ifますng-show。フォームには、コントローラーに送信できる $valid フラグがあります。

ng-if要素を DOM から削除または再作成しますが、要素をng-show追加しますが、表示しません (フラグの値によって異なります)。

編集:マイケルが指摘したように、フォームが無効になっている場合、フォームが送信されないため、私が指摘した方法は機能しません。それに応じてコードを更新しました。

HTML

<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()">
  <div>
    <label>
      Area Code
      <input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/">
    </label>

    <div ng-messages="searchForm.areaCode.$error">
      <div class="error" ng-message="pattern" ng-if="searchForm.areaCode.$dirty">The area code must be three digits</div>
    </div>
  </div>

  <div>
    <label>
      Phone Number
      <input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/">
    </label>

    <div ng-messages="searchForm.phoneNumber.$error">
      <div class="error" ng-message="pattern" ng-if="searchForm.phoneNumber.$dirty">The phone number must be seven digits</div>
    </div>
  </div>

  <br>
  <div>
    <button type="reset">Reset</button>
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button>
  </div>
</form>

JS

$scope.search = function() {
    alert('Searching');
};

$scope.reset = function(form) {
     form.$setPristine();
     form.$setUntouched();
     $scope.resetCount++;
 };

実用的なソリューションを備えた Codepen: http://codepen.io/anon/pen/zGPZoB

于 2015-06-23T18:21:15.423 に答える
1

@battmanz の回答にさらに進みますが、ES6 構文を使用して古いブラウザーをサポートすることはありません。

 $scope.resetForm = function (form) {

            try {
                var controlNames = Object.keys(form).filter(function (key) { return key.indexOf('$') !== 0 });

                console.log(controlNames);
                for (var x = 0; x < controlNames.length; x++) {
                    form[controlNames[x]].$setViewValue(undefined);
                }

                form.$setPristine();
                form.$setUntouched();
            } catch (e) {                
                console.log('Error in Reset');
                console.log(e);
            }

        };
于 2016-10-17T09:35:11.573 に答える