Reset form intact (AngularJS 1.0.x)

The function of the reset form field for the deformed state (reset dirty state) is in the roadmap for AngularJS 1.1.x. Unfortunately, this feature is not available in the current stable release.

What is the best way to reset all form fields to their original initial state for AngularJS 1.0.x.?

I would like to know if this can be fixed with a directive or another simple workaround. I prefer the solution without having to relate to the original AngularJS sources. To clarify and demonstrate the problem, reference to JSFiddle. http://jsfiddle.net/juurlink/FWGxG/7/

The desired function is in the Roadmap - http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html
Function Request - https://github.com/angular/angular.js/issues/856
Proposed Solution Request Pull - https://github.com/angular/angular.js/pull/1127

Updated with a possible workaround

Good enough workaround?

I just realized that I can recompile part of the HTML and put it back in the DOM. It works, and this is good for a workaround, but also as @blesh is mentioned in the comments:

Controllers should only be used for business logic, not for the DOM!

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

And in my controller on resetForm() :

  • Save Original Untouched HTML
  • Recompile the saved source HTML
  • Delete current form from DOM
  • Insert a new compiled template in the DOM

JavaScript:

 var pristineFormTemplate = $('#myform').html(); $scope.resetForm = function () { $('#myform').empty().append($compile(pristineFormTemplate)($scope)); } 
+60
angularjs
Sep 26
source share
7 answers

Solution without a workaround

I came up with a solution that uses AngularJS without any workarounds. The trick here is to use the ability of AngularJS to have more than one directive with the same name.

As mentioned earlier, there is actually a pull request ( https://github.com/angular/angular.js/pull/1127 ) that turned it into an AngularJS 1.1.x branch that allows forms to be reset. The end of this pull request modifies the ngModel and form / ngForm directives (I would like to add a link, but Stackoverflow doesn't want me to add more than two links).

Now we can define our own ngModel and form / ngForm directives and extend them using the functions provided in the pull request.

I wrapped these directives in an AngularJS module called resettableForm. All you have to do is include this module in your project, and your version of AngularJS version 1.0.x behaves as if it were version AngularJ 1.1.x in this regard.

'' After upgrading to 1.1.x, you don’t even need to update your code, just remove the module and you're done! ''

This module also passes all tests added to the 1.1.x branch for the reset function.

You can see the module working in the example in jsFiddle ( http://jsfiddle.net/jupiter/7jwZR/1/ ) that I created.

Step 1: Include the Resettable Shape Module in the 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 that resets the model

Remember that you must reset the model when reset form. In the 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> 
+31
Apr 30 '13 at 9:50
source share

I think it's worth mentioning that in later versions of Angular (e.g. 1.1.5) you can call $setPristine on the form.

 $scope.formName.$setPristine(true) 

It will also set all form controls to an untouched state.

FormController. $ setPristine

+81
Sep 23 '13 at 16:10
source share

EDIT ... I am deleting my old answer as it was not adequate.

Actually, I just ran into this problem, and here is my solution: I made an extension method for angular. I did this by doing a bit of what $ scope.form. $ SetValidity () did (in reverse order) ...

Here's a demo of plnkr in action

Here is the helper method I made. This is a hack, but it works:

 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]; } }; 

Hope this helps someone.

+7
Sep 26 '12 at 21:34
source share

Form fields must be associated with a variable within the scope of $. You can reset create a form by resetting variables. It should probably be a single object, for example $ scope.form.

Let's say you have a simple form for the user.

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

This will work just fine as long as your html looks like this:

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

Perhaps I do not understand this problem here, so if this does not concern your question, could you explain why?

+4
Sep 26 '12 at 19:22
source share

Here I found a solution to put this in its pristine state.

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

Just write angular.extends (src, dst) so that the original object simply expands to an empty object, which will appear as empty, and all others will be by default.

+2
Jan 11 '14 at 11:28
source share

Using an external directive and lots of 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/

+1
Mar 31 '14 at 19:48
source share

Easy way: just pass the form to the controller function. Below the form, "myForm" refers to this , which is equivalent to $ 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> 

Controller:

 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(); }) } } 
0
May 14 '16 at 16:12
source share



All Articles