将表单重置为原始状态(AngularJS 1.0.x)


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/pull/1127

更新了可能的解决方法

足够好的变通方法吗

我刚刚发现我可以重新编译HTML部分并将其放回DOM中。它起作用,对于临时解决方案来说很好,但正如@blesh在评论中提到的那样:

控制器只能用于业务逻辑,而不能用于DOM

<div id="myform">
<form class="form-horizontal" name="form">
</form>
</div>

在我的resetForm():控制器中

  • 保存原始未经修改的HTML
  • 重新编译保存的原始HTML
  • 从DOM中删除当前表单
  • 将新编译的模板插入DOM

JavaScript:

var pristineFormTemplate = $('#myform').html();
$scope.resetForm = function () {
$('#myform').empty().append($compile(pristineFormTemplate)($scope));
}

我认为值得一提的是,在Angular的后续版本(例如1.1.5)中,您可以在表单上调用$setPristine

$scope.formName.$setPristine(true)

这也将把所有表单控件设置为原始状态。

FormController$setPristine

没有解决方法的解决方案

我想出了一个解决方案,它使用AngularJS而没有任何变通方法。这里的技巧是使用AngularJS功能来拥有多个同名指令。

正如其他人提到的,实际上有一个拉取请求(https://github.com/angular/angular.js/pull/1127)它进入了AngularJS 1.1.x分支,该分支允许表单重置。对这个pull请求的提交更改了ngModel和form/ngForm指令(我本来想添加一个链接,但Stackoverflow不希望我添加两个以上的链接)。

我们现在可以定义自己的ngModel和form/ngForm指令,并使用pull请求中提供的功能对它们进行扩展。

我已经将这些指令封装在一个名为resettableForm的AngularJS模块中。您所要做的就是将这个模块包含到您的项目中,并且您的AngularJS 1.0.x版本在这方面表现得就像Angular 1.1.x版本一样。

"一旦你更新到1.1.x,你甚至不必更新你的代码,只需删除模块,你就完成了!">

此模块还通过了为表单重置功能添加到1.1.x分支的所有测试。

您可以在jsFiddle中的一个示例中看到该模块的工作情况(http://jsfiddle.net/jupiter/7jwZR/1/)我创造了。

步骤1:在项目中包含可重置表单模块

(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);

步骤2:在控制器上提供一个重置模型的方法

请注意,当你重置表单时,你必须重置模型。在你的控制器中,你可以写:

var myApp = angular.module('myApp', ['resettableForm']);
function MyCtrl($scope) {
$scope.reset = function() {
$scope.form.$setPristine();
$scope.model = '';
};
}

步骤3:在HTML模板中包含此方法

<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>

编辑。。。我要删除我以前的答案,因为它不够。

事实上,我自己也遇到了这个问题,这里是我的解决方案:我为angular做了一个扩展方法。我遵循了$scope.form.$setValidaty()的一些做法(相反)。。。

下面是它的plnkr演示

这是我制作的辅助方法。这是一个黑客,但它工作:

angular.resetForm = function (scope, formName, defaults) {
$('form[name=' + formName + '], form[name=' + formName + '] .ng-dirty').removeClass('ng-dirty').addClass('ng-pristine');
var form = scope[formName];
form.$dirty = false;
form.$pristine = true;
for(var field in form) {
if(form[field].$pristine === false) {
form[field].$pristine = true;
}
if(form[field].$dirty === true) {
form[field].$dirty = false;
}
}
for(var d in defaults) {
scope[d] = defaults[d];
}
};

希望这对某人有所帮助。

表单字段应该链接到$scope中的一个变量。您可以通过重置变量来重置表单。它可能应该是像$scope.form.这样的单个对象

假设您有一个简单的用户表单。

app.controller('Ctrl', function Ctrl($scope){
var defaultForm = {
first_name : "",
last_name : "",
address: "",
email: ""
};
$scope.resetForm = function(){
$scope.form = defaultForm;
};
});

只要你的html看起来像,这就会很好用

<form>
<input ng-model="form.first_name"/>
<input ng-model="form.last_name"/>
<input ng-model="form.address"/>
<input ng-model="form.email"/>
<button ng-click="resetForm()">Reset Form</button>
</form>

也许我不理解这里的问题,所以如果这不能解决你的问题,你能解释一下为什么吗?

这里我找到了一个将from恢复到原始状态的解决方案。

var def = {
name: '',
password: '',
email: '',
mobile: ''
};
$scope.submited = false;
$scope.regd = function (user) {
if ($scope.user.$valid) {
$http.post('saveUser', user).success(function (d) {
angular.extend($scope.user, def);
$scope.user.$setPristine(true);
$scope.user.submited = false;
}).error(function (e) {});
} else {
$scope.user.submited = true;
}
};

只需写入angular。extends(src,dst),这样您的原始对象就可以扩展空白对象,该对象将显示为空白,其余均为默认值。

使用外部指令和大量jquery

app.controller('a', function($scope) {
$scope.caca = function() {
$scope.$emit('resetForm');
}
});
app.directive('form', function() {
return {
restrict: 'E',
link: function(scope, iElem) {
scope.$on('resetForm', function() {
iElem.find('[ng-model]').andSelf().add('[ng-form]').each(function(i, elem) {
var target = $(elem).addClass('ng-pristine').removeClass('ng-dirty');
var control = target.controller('ngModel') || target.controller('form');
control.$pristine = true;
control.$dirty = false;
});
});
}
};
});

http://jsfiddle.net/pPbzz/2/

简单的方法是:将表单传递到控制器函数中。下面的表单"myForm"由this引用,相当于$scope。

<div ng-controller="MyController as mc">
<ng-form name="myform">
<input ng-model="mc.myFormValues.name" type="text" required>
<button ng-click="mc.doSometing(this.myform)" type="submit" 
ng-disabled="myform.$invalid||myform.$pristine">Do It!</button>
</ng-form>
</div>

控制器:

function MyController(MyService) {
var self = this;
self.myFormValues = {
name: 'Chris'
};
self.doSomething = function (form) {
var aform = form;
MyService.saveSomething(self.myFromValues)
.then(function (result) {
...
aform.$setPristine();
}).catch(function (e) {
...
aform.$setDirty();
})
}
}

最新更新