如何重置表单,包括删除所有验证错误?
How do I reset a form including removing all validation errors?
我有一个 Angular 表格。使用 ng-pattern
属性验证字段。我还有一个重置按钮。我正在使用 Ui.Utils Event Binder 来处理 reset
事件,如下所示:
<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>
如您所见,当表单重置时,它会调用 $scope
上的 reset
方法。这是整个控制器的样子:
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
,听从 another question 在 Stack Overflow 上的建议。我添加计数器的唯一原因是证明代码正在被调用(确实如此)。
问题是即使在重置表单后,验证消息也不会消失。您可以在 Plunker 上查看完整代码。这是显示错误不会消失的屏幕截图:
您可以在 HTML 中使用 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
我从@Brett 的评论开始,并以此为基础。我实际上有多个表单,每个表单都有很多字段(不仅仅是显示的两个)。所以我想要一个通用的解决方案。
我注意到 Angular form
对象对于每个控件(输入、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();
};
似乎没有一种简单的方法来重置 angular 中的 $errors。最好的方法可能是重新加载当前页面以从新表单开始。或者,您必须使用此脚本手动删除所有 $error:
form.$setPristine(true);
form.$setUntouched(true);
// iterate over all from properties
angular.forEach(form, function(ctrl, name) {
// ignore angular fields and functions
if (name.indexOf('$') != 0) {
// iterate over all $errors for each field
angular.forEach(ctrl.$error, function(value, name) {
// reset validity
ctrl.$setValidity(name, null);
});
}
});
$scope.resetCount++;
您可以将 loginForm 对象传递给函数 ng-click="userCtrl.login(loginForm)
在函数调用中
this.login = function (loginForm){
loginForm.$setPristine();
loginForm.$setUntouched();
}
看来我必须在 重置 时做出正确的行为。不幸的是,使用标准 reset 失败了。我也不包括库 ui-event
。所以我的代码与您的略有不同,但它可以满足您的需求。
<form name="searchForm" id="searchForm" ng-submit="search()">
pristine = {{searchForm.$pristine}} valid ={{searchForm.$valid}}
<div>
<label>
Area Code
<input type="tel" required name="areaCode" ng-model="obj.areaCode" ng-pattern="/^([0-9]{3})?$/" ng-model-options="{ allowInvalid: true }">
</label>
<div ng-messages="searchForm.areaCode.$error">
<div class="error" ng-message="pattern">The area code must be three digits</div>
<div class="error" ng-message="required">The area code is required</div>
</div>
</div>
<div>
<label>
Phone Number
<input type="tel" required name="phoneNumber" ng-model="obj.phoneNumber" ng-pattern="/^([0-9]{7})?$/" ng-model-options="{ allowInvalid: true }">
</label>
<div ng-messages="searchForm.phoneNumber.$error">
<div class="error" ng-message="pattern">The phone number must be seven digits</div>
<div class="error" ng-message="required">The phone number is required</div>
</div>
</div>
<br>
<div>
<button ng-click="reset(searchForm)" type="reset">Reset</button>
<button type="submit" ng-disabled="searchForm.$invalid">Search</button>
</div>
</form>
和 JS:
$scope.resetCount = 0;
$scope.obj = {};
$scope.reset = function(form_) {
$scope.resetCount++;
$scope.obj = {};
form_.$setPristine();
form_.$setUntouched();
console.log($scope.resetCount);
};
$scope.search = function() {
alert('Searching');
};
上的实例
注意指令 ng-model-options="{allowinvalid: true}"
。必须使用它,或者直到输入字段无效,才会记录 model 值。因此,重置不会运行。
P.S。将值(areaCode,phoneNumber)放在对象上简化净化。
$scope.search = {areaCode: xxxx, phoneNumber: yyyy}
像上面一样在一个地方构建表单中的所有模型,这样您就可以像这样清除它:
$scope.search = angular.copy({});
之后你可以调用它来重置验证:
$scope.search_form.$setPristine();
$scope.search_form.$setUntouched();
$scope.search_form.$rollbackViewValue();
@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);
}
};
以下对我有用
let form = this.$scope.myForm;
let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0);
for (let name of controlNames) {
let control = form [name];
control.$error = {};
}
简而言之: 要消除 ng-messages 错误,您需要清除 $error 每个表单项的对象。
我遇到了同样的问题并尝试做 battmanz 解决方案(已接受的答案)。
我很确定他的回答非常好,但对我来说却行不通。
我正在使用 ng-model 绑定数据,angular material 库用于输入,ng-message 指令用于错误消息,所以也许我会说仅对使用相同配置的人有用。
我仔细查看了 javascript 中的 formController 对象,实际上有很多 $ angular 函数,正如 battmanz 指出的那样,此外还有您的字段名称,这是在其字段中具有某些功能的对象。
那么什么在清除您的表格?
通常我把表单看作是一个json对象,所有字段都绑定到这个json对象的一个键上。
//lets call here this json vm.form
vm.form = {};
//you should have something as ng-model = "vm.form.name" in your view
所以首先要清除表单我只是做了提交表单的回调:
vm.form = {};
正如这个问题中所解释的,ng-messages 不会随之消失,这真的很糟糕。
当我用battmanz的解决方案,他写的时候,消息没有出现了,但是提交后字段不再是空的,即使我写了
vm.form = {};
我发现这是正常的,因为使用他的解决方案实际上从表单中删除了模型绑定,因为它将所有字段设置为未定义。
所以文本仍然在视图中,因为不知何故不再有任何绑定,它决定留在 HTML.
那我做了什么?
实际上我只是清除了字段(将绑定设置为 {}),并且只使用了
form.$setPristine();
form.$setUntouched();
实际上这似乎是合乎逻辑的,因为绑定仍然在这里,表单中的值现在是空的,并且 angular ng-messages 指令仅在表单未被触及时才会触发,所以我认为它是毕竟正常
最终(非常简单)的代码是:
function reset(form) {
form.$setPristine();
form.$setUntouched();
};
我遇到的一个大问题:
只有 一次,回调似乎在某处搞砸了,不知何故字段不是空的(就像我没有点击提交按钮一样)。
再次点击时,发送日期为空。更奇怪的是,当必填字段没有填充正确的模式时,我的提交按钮应该被禁用,而空的肯定不是一个好模式。
我不知道我的做法是不是最好的,甚至是正确的,如果您对我遇到的问题有任何critic/suggestion或任何想法,请告诉我,我总是喜欢一步在 angularJS.
希望这对某人有所帮助,抱歉英语不好。
所以 none 的答案完全适合我。 Esp,清除视图值,所以我将所有清除视图值、清除错误和清除选择的答案与 j 查询结合起来(前提是输入的字段和名称与模型名称相同)
var modelNames = Object.keys($scope.form).filter(key => key.indexOf('$') !== 0);
modelNames.forEach(function(name){
var model = $scope.form[name];
model.$setViewValue(undefined);
jq('input[name='+name+']').val('');
angular.forEach(model.$error, function(value, name) {
// reset validity
model.$setValidity(name, null);
});
});
$scope.form.$setPristine();
$scope.form.$setUntouched();
我有一个 Angular 表格。使用 ng-pattern
属性验证字段。我还有一个重置按钮。我正在使用 Ui.Utils Event Binder 来处理 reset
事件,如下所示:
<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>
如您所见,当表单重置时,它会调用 $scope
上的 reset
方法。这是整个控制器的样子:
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
,听从 another question 在 Stack Overflow 上的建议。我添加计数器的唯一原因是证明代码正在被调用(确实如此)。
问题是即使在重置表单后,验证消息也不会消失。您可以在 Plunker 上查看完整代码。这是显示错误不会消失的屏幕截图:
您可以在 HTML 中使用 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
我从@Brett 的评论开始,并以此为基础。我实际上有多个表单,每个表单都有很多字段(不仅仅是显示的两个)。所以我想要一个通用的解决方案。
我注意到 Angular form
对象对于每个控件(输入、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();
};
似乎没有一种简单的方法来重置 angular 中的 $errors。最好的方法可能是重新加载当前页面以从新表单开始。或者,您必须使用此脚本手动删除所有 $error:
form.$setPristine(true);
form.$setUntouched(true);
// iterate over all from properties
angular.forEach(form, function(ctrl, name) {
// ignore angular fields and functions
if (name.indexOf('$') != 0) {
// iterate over all $errors for each field
angular.forEach(ctrl.$error, function(value, name) {
// reset validity
ctrl.$setValidity(name, null);
});
}
});
$scope.resetCount++;
您可以将 loginForm 对象传递给函数 ng-click="userCtrl.login(loginForm)
在函数调用中
this.login = function (loginForm){
loginForm.$setPristine();
loginForm.$setUntouched();
}
看来我必须在 重置 时做出正确的行为。不幸的是,使用标准 reset 失败了。我也不包括库 ui-event
。所以我的代码与您的略有不同,但它可以满足您的需求。
<form name="searchForm" id="searchForm" ng-submit="search()">
pristine = {{searchForm.$pristine}} valid ={{searchForm.$valid}}
<div>
<label>
Area Code
<input type="tel" required name="areaCode" ng-model="obj.areaCode" ng-pattern="/^([0-9]{3})?$/" ng-model-options="{ allowInvalid: true }">
</label>
<div ng-messages="searchForm.areaCode.$error">
<div class="error" ng-message="pattern">The area code must be three digits</div>
<div class="error" ng-message="required">The area code is required</div>
</div>
</div>
<div>
<label>
Phone Number
<input type="tel" required name="phoneNumber" ng-model="obj.phoneNumber" ng-pattern="/^([0-9]{7})?$/" ng-model-options="{ allowInvalid: true }">
</label>
<div ng-messages="searchForm.phoneNumber.$error">
<div class="error" ng-message="pattern">The phone number must be seven digits</div>
<div class="error" ng-message="required">The phone number is required</div>
</div>
</div>
<br>
<div>
<button ng-click="reset(searchForm)" type="reset">Reset</button>
<button type="submit" ng-disabled="searchForm.$invalid">Search</button>
</div>
</form>
和 JS:
$scope.resetCount = 0;
$scope.obj = {};
$scope.reset = function(form_) {
$scope.resetCount++;
$scope.obj = {};
form_.$setPristine();
form_.$setUntouched();
console.log($scope.resetCount);
};
$scope.search = function() {
alert('Searching');
};
上的实例
注意指令 ng-model-options="{allowinvalid: true}"
。必须使用它,或者直到输入字段无效,才会记录 model 值。因此,重置不会运行。
P.S。将值(areaCode,phoneNumber)放在对象上简化净化。
$scope.search = {areaCode: xxxx, phoneNumber: yyyy}
像上面一样在一个地方构建表单中的所有模型,这样您就可以像这样清除它:
$scope.search = angular.copy({});
之后你可以调用它来重置验证:
$scope.search_form.$setPristine();
$scope.search_form.$setUntouched();
$scope.search_form.$rollbackViewValue();
@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);
}
};
以下对我有用
let form = this.$scope.myForm;
let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0);
for (let name of controlNames) {
let control = form [name];
control.$error = {};
}
简而言之: 要消除 ng-messages 错误,您需要清除 $error 每个表单项的对象。
我遇到了同样的问题并尝试做 battmanz 解决方案(已接受的答案)。
我很确定他的回答非常好,但对我来说却行不通。
我正在使用 ng-model 绑定数据,angular material 库用于输入,ng-message 指令用于错误消息,所以也许我会说仅对使用相同配置的人有用。
我仔细查看了 javascript 中的 formController 对象,实际上有很多 $ angular 函数,正如 battmanz 指出的那样,此外还有您的字段名称,这是在其字段中具有某些功能的对象。
那么什么在清除您的表格?
通常我把表单看作是一个json对象,所有字段都绑定到这个json对象的一个键上。
//lets call here this json vm.form
vm.form = {};
//you should have something as ng-model = "vm.form.name" in your view
所以首先要清除表单我只是做了提交表单的回调:
vm.form = {};
正如这个问题中所解释的,ng-messages 不会随之消失,这真的很糟糕。
当我用battmanz的解决方案,他写的时候,消息没有出现了,但是提交后字段不再是空的,即使我写了
vm.form = {};
我发现这是正常的,因为使用他的解决方案实际上从表单中删除了模型绑定,因为它将所有字段设置为未定义。 所以文本仍然在视图中,因为不知何故不再有任何绑定,它决定留在 HTML.
那我做了什么?
实际上我只是清除了字段(将绑定设置为 {}),并且只使用了
form.$setPristine();
form.$setUntouched();
实际上这似乎是合乎逻辑的,因为绑定仍然在这里,表单中的值现在是空的,并且 angular ng-messages 指令仅在表单未被触及时才会触发,所以我认为它是毕竟正常
最终(非常简单)的代码是:
function reset(form) {
form.$setPristine();
form.$setUntouched();
};
我遇到的一个大问题:
只有 一次,回调似乎在某处搞砸了,不知何故字段不是空的(就像我没有点击提交按钮一样)。
再次点击时,发送日期为空。更奇怪的是,当必填字段没有填充正确的模式时,我的提交按钮应该被禁用,而空的肯定不是一个好模式。
我不知道我的做法是不是最好的,甚至是正确的,如果您对我遇到的问题有任何critic/suggestion或任何想法,请告诉我,我总是喜欢一步在 angularJS.
希望这对某人有所帮助,抱歉英语不好。
所以 none 的答案完全适合我。 Esp,清除视图值,所以我将所有清除视图值、清除错误和清除选择的答案与 j 查询结合起来(前提是输入的字段和名称与模型名称相同)
var modelNames = Object.keys($scope.form).filter(key => key.indexOf('$') !== 0);
modelNames.forEach(function(name){
var model = $scope.form[name];
model.$setViewValue(undefined);
jq('input[name='+name+']').val('');
angular.forEach(model.$error, function(value, name) {
// reset validity
model.$setValidity(name, null);
});
});
$scope.form.$setPristine();
$scope.form.$setUntouched();