HOWTO · Angular
AngularJS setPristine でフォームをリセット
このチュートリアルでは、AngularJS のフォームコントローラーで `$setPristine()` を呼び出し、フォームと各コントロールの操作状態を pristine に戻す方法を説明します。このメソッドはモデル値を変更しないため、入力値を消去または復元する場合は、モデルを別途更新します。
このページの内容
AngularJS でフォームをリセットするとは、操作状態をリセットすること、フィールドにバインドされた値を変更すること、またはその両方を行うことを意味します。フォームコントローラーの $setPristine() メソッドを呼び出すと、フォームと各コントロールを再び pristine 状態にできます。ただし、untouched 状態にはならず、モデル値も変わりません。入力値を消去または復元したい場合は、モデルを別途更新してください。
pristine 状態、dirty 状態、モデル値を理解する
$setPristine() はメソッドです。一方、$pristine と $dirty は、フォームまたはコントロールが持つ真偽値の状態プロパティです。フォームは最初 pristine 状態です。ユーザーがコントロールの値を変更すると、AngularJS によって、そのコントロールと親フォームが dirty 状態になります。$setPristine() を呼び出すと pristine/dirty 状態はリセットされますが、元の値に戻ったり、モデルが空になったりするわけではありません。
touched 状態は別です。$touched と $untouched はコントロールからフォーカスが外れたかどうかを表し、pristine/dirty は値が変更されたかどうかを表します。$setPristine() は touched 状態をリセットしません。コントロールを untouched に戻す必要もある場合は、フォームの $setUntouched() メソッドを別途呼び出してください。必要がなければ touched 状態には手を加えません。
名前付きフォームコントローラーは、フォームの name に基づいて親スコープに公開されます。以下の例では、アプリケーションコントローラーに controller-as 構文(vm)を使い、フォームコントローラーには $scope.profileForm でアクセスします。入力欄を ng-model でバインドし、フィールドを消去または復元するときは、同じモデルプロパティを使ってください。
$setPristine() でフォーム状態をリセットする
このブラウザー向けのコード例では、フォーム、ボタン、コントローラー、名前付きフォームコントローラーのつながりを示します。ページで AngularJS が読み込まれていることを前提としています。最初のボタンは現在のフィールド値を保ったままフォーム状態をリセットし、2つ目のボタンはモデル値を消去してから状態をリセットします。
このセクションのコードと、コード内に表示されるラベルや出力は英語のままです。
<div ng-app="myApp" ng-controller="FormController as vm">
<form name="profileForm">
<label>
Name
<input name="name" ng-model="vm.profile.name">
</label>
<button type="button" ng-click="vm.resetState()">Mark form pristine</button>
<button type="button" ng-click="vm.clearAndReset()">Clear and reset</button>
</form>
</div>
<script>
angular.module('myApp', []).controller('FormController', function ($scope) {
var vm = this;
vm.profile = { name: 'Ada' };
vm.resetState = function () {
$scope.profileForm.$setPristine();
};
vm.clearAndReset = function () {
vm.profile.name = '';
$scope.profileForm.$setPristine();
};
vm.restoreAndReset = function () {
vm.profile.name = 'Ada';
$scope.profileForm.$setPristine();
};
});
</script>
ハンドラーは ng-controller で指定したものと同じ vm インスタンスに定義されており、各ボタンは定義済みのメソッドを呼び出します。AngularJS はフォームのリンク処理後、名前付きフォームコントローラーを $scope から利用できるようにするため、クリックハンドラーから $scope.profileForm.$setPristine() を呼び出せます。resetState() は vm.profile.name を変更しません。clearAndReset() はフォーム状態をリセットする前に、そのモデルプロパティを変更します。別の restoreAndReset() メソッドは保存済みの値を復元する例です。必要に応じてボタンなどのアプリケーション操作から呼び出してください。
モデル値は別途消去または復元する
操作状態のリセットとフィールド値の変更は、それぞれ独立した操作です。現在の値を保つには、モデルに代入せず $setPristine() を呼び出します。値を消去するにはバインドされたプロパティに空文字列を代入し、復元するには保存しておいた値を代入します。値と操作状態の両方をリセットする場合は、上の該当するハンドラーのように、モデルを更新してから $setPristine() を呼び出してください。
以下の単独で実行できる JavaScript シミュレーションは、実行環境に AngularJS がなくても、この2つの操作を示します。モデル化しているのは状態と値の変化だけであり、AngularJS のフォーム実装ではありません。
この例を実行してください。
このセクションのコードと、コード内に表示されるラベルや出力は英語のままです。
const form = {
$dirty: true,
$pristine: false,
$setPristine() {
this.$dirty = false;
this.$pristine = true;
}
};
const model = { name: 'Ada' };
model.name = '';
form.$setPristine();
console.log(JSON.stringify({ name: model.name, pristine: form.$pristine, dirty: form.$dirty }));
{"name":"","pristine":true,"dirty":false}
このシミュレーションでは、model.name = '' を代入すると値が消去され、$setPristine() はモデル化した操作状態のフラグだけを変更します。値を維持する動作を試すには、代入を省略します。保存済みの値を復元する動作を試すには、フラグをリセットする前にその値を代入します。AngularJS アプリケーションでは、ブラウザー向けのコード例に示した実際のモデルプロパティとフォームコントローラーを使用してください。
動作を確認し、よくある誤りを避ける
ハンドラーの実行後、名前付きフォームの $pristine と $dirty プロパティを調べ、vm.profile.name も別途確認します。resetState() を使うと、現在の値を保ったままフォームが pristine 状態になります。clearAndReset() を使うと、値が空になり、フォームが pristine 状態になります。モデルに値を代入するだけでは $setPristine() は呼び出されません。両方の結果が必要なら、両方の操作を行ってください。
pristine/dirty と touched/untouched を同じ状態として扱わないでください。フォーカス状態もリセットする必要がある場合に限り $setUntouched() を使います。$setPristine を状態そのものと呼んだり、誤記された $errror プロパティを検証に使ったりしないでください。必須項目のエラーメッセージには、profileForm.name.$error.required のような正しい検証プロパティを確認します。リセットボタンの type="button" はフォームの送信を防ぎます。この手順では AngularJS に組み込まれているフォームコントローラーを使用するため、フォームディレクティブの置き換えやコントローラーメソッドの上書きは不要です。