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>