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 内置的表单控制器,无需替换表单指令或覆盖控制器方法。