问题描述
将表单字段重置为原始状态(重置脏状态)的功能在 AngularJS 1.1.x 的路线图上.不幸的是,当前的稳定版本中缺少这样的功能.
对于 AngularJS 1.0.x.,将所有表单字段重置为其初始原始状态的最佳方法是什么?
我想知道这是否可以通过指令或其他简单的解决方法解决.我更喜欢无需接触原始 AngularJS 源代码的解决方案.为了澄清和演示该问题,请提供指向 JSFiddle 的链接.http://jsfiddle.net/juurlink/FWGxG/7/
所需功能在路线图 - http:///blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html
功能请求 - https://github.com/angular/angular.js/issues/856
提议的解决方案拉取请求 - https://github.com/angular/angular.js/拉/1127
更新了可能的解决方法
足够好的解决方法?
我刚刚发现我可以重新编译 HTML 部分并将其放回 DOM 中.它有效并且可以作为临时解决方案,但也如评论中提到的@blesh:
控制器应该只用于业务逻辑,而不是用于 DOM!
<form class="form-horizontal" name="form"></表单>
在我的控制器中 resetForm()
:
- 保存原始未改动的 HTML
- 重新编译保存的原始 HTML
- 从 DOM 中移除当前表单
- 将新编译的模板插入到 DOM 中
JavaScript:
var pristineFormTemplate = $('#myform').html();$scope.resetForm = 函数 () {$('#myform').empty().append($compile(pristineFormTemplate)($scope));}
没有变通方法的解决方案
我想出了一个使用 AngularJS 而没有任何解决方法的解决方案.这里的技巧是使用 AngularJS 的能力来拥有多个同名指令.
正如其他人提到的,实际上有一个拉取请求(https://github.com/angular/angular.js/pull/1127) 使其成为允许表单重置的 AngularJS 1.1.x 分支.对这个拉取请求的提交改变了 ngModel 和 form/ngForm 指令(我本来想添加一个链接,但 Stackoverflow 不希望我添加两个以上的链接).
我们现在可以定义我们自己的 ngModel 和 form/ngForm 指令,并使用拉取请求中提供的功能扩展它们.
我已将这些指令包装在名为 resettableForm 的 AngularJS 模块中.您所要做的就是将此模块包含到您的项目中,并且您的 AngularJS 1.0.x 版在这方面就像是 Angular 1.1.x 版一样.
''更新到 1.1.x 后,您甚至不必更新代码,只需删除模块即可完成!''
该模块还通过了为表单重置功能添加到 1.1.x 分支的所有测试.
您可以在 jsFiddle (http://jsfiddle.net/jupiter/7jwZR/1/) 我创建的.
步骤 1:在您的项目中包含 resettableform 模块
(function(angular) {//复制自AngluarJS函数 indexOf(array, obj) {if (array.indexOf) return array.indexOf(obj);for ( var i = 0; i < array.length; i++) {if (obj === array[i]) 返回 i;}返回-1;}//复制自 AngularJS函数数组移除(数组,值){var index = indexOf(array, value);如果(索引>=0)array.splice(index, 1);返回值;}//复制自 AngularJSvar PRISTINE_CLASS = 'ng-pristine';var DIRTY_CLASS = 'ng-dirty';var formDirectiveFactory = function(isNgForm) {返回函数(){var formDirective = {限制:'E',要求:['表格'],编译:函数(){返回 {前:功能(范围,元素,属性,ctrls){var form = ctrls[0];var $addControl = form.$addControl;var $removeControl = form.$removeControl;var 控件 = [];form.$addControl = 函数(控件){控制推(控制);$addControl.apply(this, arguments);}form.$removeControl = 函数(控制){arrayRemove(控件,控件);$removeControl.apply(this, arguments);}form.$setPristine = function() {element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);form.$dirty = false;form.$pristine = true;angular.forEach(controls, function(control) {control.$setPristine();});}},};},};返回 isNgForm ?angular.extend(angular.copy(formDirective), {restrict: 'EAC'}) : formDirective;};}var ngFormDirective = formDirectiveFactory(true);var formDirective = formDirectiveFactory();angular.module('resettableForm', []).指令('ngForm',ngFormDirective).指令('form',formDirective).指令('ngModel',函数(){返回 {要求:['ngModel'],链接:函数(范围,元素,属性,ctrls){var control = ctrls[0];control.$setPristine = function() {this.$dirty = false;this.$pristine = true;element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);}},};});})(角度);
第 2 步:在控制器上提供一个方法来重置模型
请注意,您必须在重置表单时重置模型.在您的控制器中,您可以编写:
var myApp = angular.module('myApp', ['resettableForm']);函数 MyCtrl($scope) {$scope.reset = function() {$scope.form.$setPristine();$scope.model = '';};}
第 3 步:在您的 HTML 模板中包含此方法
<div ng-controller="MyCtrl"><表格名称=表格"><input name="requiredField" ng-model="model.requiredField" required/>(必需,但没有其他验证器)<p ng-show="form.requiredField.$errror.required">必填字段</p><button ng-click="reset()">重置表单</button></表单><p>Pristine:{{form.$pristine}}</p>
A function to reset form fields to pristine state (reset dirty state) is on the roadmap for AngularJS 1.1.x. Unfortunately such a function is missing from the current stable release.
What is the best way to reset all form fields to their initial pristine state for AngularJS 1.0.x.?
I would like to know if this is fixable with a directive or other simple workaround. I prefer a solution without having to touch the original AngularJS sources. To clarify and demonstrate the problem, a link to JSFiddle. http://jsfiddle.net/juurlink/FWGxG/7/
Desired feature is on the Roadmap - http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html
Feature request - https://github.com/angular/angular.js/issues/856
Proposed solution Pull request - https://github.com/angular/angular.js/pull/1127
Updated with possible workaround
Good enough workaround?
I just figured out I can recompile the HTML part and put it back into the DOM. It works and it's fine for a temporarily solution, but also as @blesh mentioned in the comments:
Controllers should be used for business logic only, not for DOM!
<div id="myform">
<form class="form-horizontal" name="form">
</form>
</div>
And in my Controller on resetForm()
:
- Save the original untouched HTML
- Recompile the saved original HTML
- Remove the current form from the DOM
- Insert the new compiled template into the DOM
The JavaScript:
var pristineFormTemplate = $('#myform').html();
$scope.resetForm = function () {
$('#myform').empty().append($compile(pristineFormTemplate)($scope));
}
Solution without a workaround
I came up with a solution which uses AngularJS without any workaround. The trick here is to use AngularJS ability to have more than one directive with the same name.
As others mentioned there is actually a pull request (https://github.com/angular/angular.js/pull/1127) which made it into the AngularJS 1.1.x branch which allows forms to be reset. The commit to this pull request alters the ngModel and form/ngForm directives (I would have liked to add a link but Stackoverflow doesn't want me to add more than two links).
We can now define our own ngModel and form/ngForm directives and extend them with the functionality provided in the pull request.
I have wrapped these directives in a AngularJS module named resettableForm. All you have to do is to include this module to your project and your AngularJS version 1.0.x behaves as if it was an Angular 1.1.x version in this regard.
''Once you update to 1.1.x you don't even have to update your code, just remove the module and you are done!''
This module also passes all tests added to the 1.1.x branch for the form reset functionality.
You can see the module working in an example in a jsFiddle (http://jsfiddle.net/jupiter/7jwZR/1/) I created.
Step 1: Include the resettableform module in your project
(function(angular) {
// Copied from AngluarJS
function indexOf(array, obj) {
if (array.indexOf) return array.indexOf(obj);
for ( var i = 0; i < array.length; i++) {
if (obj === array[i]) return i;
}
return -1;
}
// Copied from AngularJS
function arrayRemove(array, value) {
var index = indexOf(array, value);
if (index >=0)
array.splice(index, 1);
return value;
}
// Copied from AngularJS
var PRISTINE_CLASS = 'ng-pristine';
var DIRTY_CLASS = 'ng-dirty';
var formDirectiveFactory = function(isNgForm) {
return function() {
var formDirective = {
restrict: 'E',
require: ['form'],
compile: function() {
return {
pre: function(scope, element, attrs, ctrls) {
var form = ctrls[0];
var $addControl = form.$addControl;
var $removeControl = form.$removeControl;
var controls = [];
form.$addControl = function(control) {
controls.push(control);
$addControl.apply(this, arguments);
}
form.$removeControl = function(control) {
arrayRemove(controls, control);
$removeControl.apply(this, arguments);
}
form.$setPristine = function() {
element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
form.$dirty = false;
form.$pristine = true;
angular.forEach(controls, function(control) {
control.$setPristine();
});
}
},
};
},
};
return isNgForm ? angular.extend(angular.copy(formDirective), {restrict: 'EAC'}) : formDirective;
};
}
var ngFormDirective = formDirectiveFactory(true);
var formDirective = formDirectiveFactory();
angular.module('resettableForm', []).
directive('ngForm', ngFormDirective).
directive('form', formDirective).
directive('ngModel', function() {
return {
require: ['ngModel'],
link: function(scope, element, attrs, ctrls) {
var control = ctrls[0];
control.$setPristine = function() {
this.$dirty = false;
this.$pristine = true;
element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
}
},
};
});
})(angular);
Step 2: Provide a method on your controller which resets the model
Please be aware that you must reset the model when you reset the form. In your controller you can write:
var myApp = angular.module('myApp', ['resettableForm']);
function MyCtrl($scope) {
$scope.reset = function() {
$scope.form.$setPristine();
$scope.model = '';
};
}
Step 3: Include this method in your HTML template
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<form name="form">
<input name="requiredField" ng-model="model.requiredField" required/> (Required, but no other validators)
<p ng-show="form.requiredField.$errror.required">Field is required</p>
<button ng-click="reset()">Reset form</button>
</form>
<p>Pristine: {{form.$pristine}}</p>
</div>
</dvi>
这篇关于将表单重置为原始状态 (AngularJS 1.0.x)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!