Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset form to pristine state (AngularJS 1.0.x)

Tags:

angularjs

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)); } 
like image 997
Rob Juurlink Avatar asked Sep 26 '12 14:09

Rob Juurlink


People also ask

How would you reset all objects on a form?

If you take a look at the reset button of the first form, Toggle submit, you will notice that it calls a method resetForm() on the click event of the button. Similarly the second form, Always submit, calls a method reset() . Both methods are called on the heroForm object.

How do you make a pristine false form?

Using $setPristine will set the $pristine property of the form to true and $dirty to false. $setDirty will do the contrary.

How to reset form dirty AngularJS?

We can reset the $dirty value to false manually but afterwards when you again change your form field values $dirty won't change its value to true. According to my observation it set $dirty value of every field in your form by placing ng-dirty class. Even if you remove that class it is not affecting $dirty behavior.


2 Answers

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) 

This will set all the form controls to pristine state as well.

FormController.$setPristine

like image 196
Matthias Avatar answered Sep 16 '22 12:09

Matthias


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> 
like image 45
jupiter Avatar answered Sep 18 '22 12:09

jupiter