mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +00:00
feat(form): add ability to reset a form to pristine state
Retting a form to pristine state will cause all of the nested form and form controls to be recursively reset as well. Closes #856
This commit is contained in:
parent
96ed9ff59a
commit
733a97adf8
4 changed files with 165 additions and 2 deletions
|
|
@ -5,7 +5,8 @@ var nullFormCtrl = {
|
|||
$addControl: noop,
|
||||
$removeControl: noop,
|
||||
$setValidity: noop,
|
||||
$setDirty: noop
|
||||
$setDirty: noop,
|
||||
$setPristine: noop
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -37,7 +38,8 @@ function FormController(element, attrs) {
|
|||
var form = this,
|
||||
parentForm = element.parent().controller('form') || nullFormCtrl,
|
||||
invalidCount = 0, // used to easily determine if we are valid
|
||||
errors = form.$error = {};
|
||||
errors = form.$error = {},
|
||||
controls = [];
|
||||
|
||||
// init state
|
||||
form.$name = attrs.name;
|
||||
|
|
@ -61,6 +63,8 @@ function FormController(element, attrs) {
|
|||
}
|
||||
|
||||
form.$addControl = function(control) {
|
||||
controls.push(control);
|
||||
|
||||
if (control.$name && !form.hasOwnProperty(control.$name)) {
|
||||
form[control.$name] = control;
|
||||
}
|
||||
|
|
@ -73,6 +77,8 @@ function FormController(element, attrs) {
|
|||
forEach(errors, function(queue, validationToken) {
|
||||
form.$setValidity(validationToken, true, control);
|
||||
});
|
||||
|
||||
arrayRemove(controls, control);
|
||||
};
|
||||
|
||||
form.$setValidity = function(validationToken, isValid, control) {
|
||||
|
|
@ -120,6 +126,29 @@ function FormController(element, attrs) {
|
|||
parentForm.$setDirty();
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name ng.directive:form.FormController#$setPristine
|
||||
* @methodOf ng.directive:form.FormController
|
||||
*
|
||||
* @description
|
||||
* Sets the form to its pristine state.
|
||||
*
|
||||
* This method can be called to remove the 'ng-dirty' class and set the form to its pristine
|
||||
* state (ng-pristine class). This method will also propagate to all the controls contained
|
||||
* in this form.
|
||||
*
|
||||
* Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
|
||||
* saving or resetting it.
|
||||
*/
|
||||
form.$setPristine = function () {
|
||||
element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
|
||||
form.$dirty = false;
|
||||
form.$pristine = true;
|
||||
forEach(controls, function(control) {
|
||||
control.$setPristine();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -978,6 +978,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|||
parentForm.$setValidity(validationErrorKey, isValid, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name ng.directive:ngModel.NgModelController#$setPristine
|
||||
* @methodOf ng.directive:ngModel.NgModelController
|
||||
*
|
||||
* @description
|
||||
* Sets the control to its pristine state.
|
||||
*
|
||||
* This method can be called to remove the 'ng-dirty' class and set the control to its pristine
|
||||
* state (ng-pristine class).
|
||||
*/
|
||||
this.$setPristine = function () {
|
||||
this.$dirty = false;
|
||||
this.$pristine = true;
|
||||
$element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
|
|
|
|||
|
|
@ -430,4 +430,110 @@ describe('form', function() {
|
|||
expect(doc).toBeDirty();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('$setPristine', function() {
|
||||
|
||||
it('should reset pristine state of form and controls', function() {
|
||||
|
||||
doc = $compile(
|
||||
'<form name="testForm">' +
|
||||
'<input ng-model="named1" name="foo">' +
|
||||
'<input ng-model="named2" name="bar">' +
|
||||
'</form>')(scope);
|
||||
|
||||
scope.$digest();
|
||||
|
||||
var form = doc,
|
||||
formCtrl = scope.testForm,
|
||||
input1 = form.find('input').eq(0),
|
||||
input1Ctrl = input1.controller('ngModel'),
|
||||
input2 = form.find('input').eq(1),
|
||||
input2Ctrl = input2.controller('ngModel');
|
||||
|
||||
input1Ctrl.$setViewValue('xx');
|
||||
input2Ctrl.$setViewValue('yy');
|
||||
scope.$apply();
|
||||
expect(form).toBeDirty();
|
||||
expect(input1).toBeDirty();
|
||||
expect(input2).toBeDirty();
|
||||
|
||||
formCtrl.$setPristine();
|
||||
expect(form).toBePristine();
|
||||
expect(formCtrl.$pristine).toBe(true);
|
||||
expect(formCtrl.$dirty).toBe(false);
|
||||
expect(input1).toBePristine();
|
||||
expect(input1Ctrl.$pristine).toBe(true);
|
||||
expect(input1Ctrl.$dirty).toBe(false);
|
||||
expect(input2).toBePristine();
|
||||
expect(input2Ctrl.$pristine).toBe(true);
|
||||
expect(input2Ctrl.$dirty).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
it('should reset pristine state of anonymous form controls', function() {
|
||||
|
||||
doc = $compile(
|
||||
'<form name="testForm">' +
|
||||
'<input ng-model="anonymous">' +
|
||||
'</form>')(scope);
|
||||
|
||||
scope.$digest();
|
||||
|
||||
var form = doc,
|
||||
formCtrl = scope.testForm,
|
||||
input = form.find('input').eq(0),
|
||||
inputCtrl = input.controller('ngModel');
|
||||
|
||||
inputCtrl.$setViewValue('xx');
|
||||
scope.$apply();
|
||||
expect(form).toBeDirty();
|
||||
expect(input).toBeDirty();
|
||||
|
||||
formCtrl.$setPristine();
|
||||
expect(form).toBePristine();
|
||||
expect(formCtrl.$pristine).toBe(true);
|
||||
expect(formCtrl.$dirty).toBe(false);
|
||||
expect(input).toBePristine();
|
||||
expect(inputCtrl.$pristine).toBe(true);
|
||||
expect(inputCtrl.$dirty).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
it('should reset pristine state of nested forms', function() {
|
||||
|
||||
doc = $compile(
|
||||
'<form name="testForm">' +
|
||||
'<div ng-form>' +
|
||||
'<input ng-model="named" name="foo">' +
|
||||
'</div>' +
|
||||
'</form>')(scope);
|
||||
|
||||
scope.$digest();
|
||||
|
||||
var form = doc,
|
||||
formCtrl = scope.testForm,
|
||||
nestedForm = form.find('div'),
|
||||
nestedFormCtrl = nestedForm.controller('form'),
|
||||
nestedInput = form.find('input').eq(0),
|
||||
nestedInputCtrl = nestedInput.controller('ngModel');
|
||||
|
||||
nestedInputCtrl.$setViewValue('xx');
|
||||
scope.$apply();
|
||||
expect(form).toBeDirty();
|
||||
expect(nestedForm).toBeDirty();
|
||||
expect(nestedInput).toBeDirty();
|
||||
|
||||
formCtrl.$setPristine();
|
||||
expect(form).toBePristine();
|
||||
expect(formCtrl.$pristine).toBe(true);
|
||||
expect(formCtrl.$dirty).toBe(false);
|
||||
expect(nestedForm).toBePristine();
|
||||
expect(nestedFormCtrl.$pristine).toBe(true);
|
||||
expect(nestedFormCtrl.$dirty).toBe(false);
|
||||
expect(nestedInput).toBePristine();
|
||||
expect(nestedInputCtrl.$pristine).toBe(true);
|
||||
expect(nestedInputCtrl.$dirty).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -117,6 +117,18 @@ describe('NgModelController', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('setPristine', function() {
|
||||
|
||||
it('should set control to its pristine state', function() {
|
||||
ctrl.$setViewValue('edit');
|
||||
expect(ctrl.$dirty).toBe(true);
|
||||
expect(ctrl.$pristine).toBe(false);
|
||||
|
||||
ctrl.$setPristine();
|
||||
expect(ctrl.$dirty).toBe(false);
|
||||
expect(ctrl.$pristine).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('view -> model', function() {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue