HOWTO · Angular
AngularJS setPristine 重置表单
本教程说明如何使用 AngularJS 的 `$setPristine()` 重置表单交互状态;清空或恢复字段值时,需另外更新模型。
本页内容
在 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 为名称发布到所在的 scope 上。下面的示例使用 vm 作为应用控制器的 controller-as 别名,并通过 $scope.profileForm 访问表单控制器。使用 ng-model 绑定输入字段;清空或恢复字段时,也要操作同一个模型属性。
使用 $setPristine() 重置表单状态
这个浏览器端代码示例展示了如何连接表单、按钮、控制器和具名表单控制器。它假设页面已加载 AngularJS。第一个按钮会保留当前字段值并重置表单状态;第二个按钮会清空模型,然后重置状态。示例中的按钮文字保留英文。
本节中的代码以及显示的标签或输出仍为英文。
<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。它只模拟状态和值的变化,并不是 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() 只会更改模拟的交互标志。代码输出中的字段名 name、pristine 和 dirty 保留英文,分别表示模型值以及表单状态。若要模拟保留该值,请省略赋值操作;若要模拟恢复已保存的值,请在重置标志之前赋回该值。在 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 内置的表单控制器,无需替换表单指令或覆盖控制器方法。