Skip to content

Commit c81a7fa

Browse files
committed
fix(ngModel): remove reference to parentForm from removed control
Otherwise, once the removed control's validity changes, it will continue to be reflected on its former parent form. Fixes angular#12263
1 parent cf28c1a commit c81a7fa

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

Diff for: src/ng/directive/form.js

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
168168
});
169169

170170
arrayRemove(controls, control);
171+
control.$$parentForm = nullFormCtrl;
171172
};
172173

173174

Diff for: src/ng/directive/ngModel.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
237237
this.$pending = undefined; // keep pending keys here
238238
this.$name = $interpolate($attr.name || '', false)($scope);
239239

240+
var parentForm = this.$$parentForm = $element.inheritedData('$formController') || nullFormCtrl
240241

241242
var parsedNgModel = $parse($attr.ngModel),
242243
parsedNgModelAssign = parsedNgModel.assign,
@@ -316,8 +317,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
316317
return isUndefined(value) || value === '' || value === null || value !== value;
317318
};
318319

319-
var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
320-
currentValidationRunId = 0;
320+
var currentValidationRunId = 0;
321321

322322
/**
323323
* @ngdoc method
@@ -350,7 +350,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
350350
unset: function(object, property) {
351351
delete object[property];
352352
},
353-
parentForm: parentForm,
354353
$animate: $animate
355354
});
356355

@@ -1258,7 +1257,6 @@ function addSetValidityMethod(context) {
12581257
classCache = {},
12591258
set = context.set,
12601259
unset = context.unset,
1261-
parentForm = context.parentForm,
12621260
$animate = context.$animate;
12631261

12641262
classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
@@ -1310,7 +1308,7 @@ function addSetValidityMethod(context) {
13101308
}
13111309

13121310
toggleValidationCss(validationErrorKey, combinedState);
1313-
parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
1311+
ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
13141312
}
13151313

13161314
function createAndSet(name, value, controller) {

Diff for: test/ng/directive/formSpec.js

+44
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,50 @@ describe('form', function() {
5858
expect(form.alias).toBeUndefined();
5959
});
6060

61+
it('should ignore the validity of removed form control references', function() {
62+
doc = $compile(
63+
'<form name="myForm">' +
64+
'<input name="control" ng-maxlength="1" ng-model="value" store-model-ctrl/>' +
65+
'<ng-form name="childform">' +
66+
'<input name="childformcontrol" ng-maxlength="1" ng-model="value"/>' +
67+
'</ng-form>' +
68+
'</form>')(scope);
69+
70+
var form = scope.myForm;
71+
var childformController = doc.find('ng-form').eq(0).controller('form');
72+
73+
var input = doc.find('input').eq(0);
74+
var childforminput = doc.find('input').eq(1);
75+
76+
changeInputValue(input, 'ab');
77+
changeInputValue(childforminput, 'ab');
78+
scope.$apply();
79+
80+
expect(form.$error.maxlength).toBeTruthy();
81+
expect(form.$error.maxlength[0].$name).toBe('control');
82+
expect(form.$error.maxlength[1].$name).toBe('childform');
83+
84+
// remove child form
85+
form.$removeControl(childformController);
86+
expect(form.childform).toBeUndefined();
87+
88+
expect(form.$error.maxlength.length).toBe(1);
89+
expect(form.$error.maxlength[0].$name).toBe('control');
90+
91+
// remove control
92+
form.$removeControl(form.control);
93+
expect(form.control).toBeUndefined();
94+
95+
expect(form.$error.maxlength).toBeFalsy();
96+
97+
changeInputValue(input, 'abc');
98+
changeInputValue(childforminput, 'abc');
99+
scope.$apply();
100+
101+
expect(form.$error.maxlength).toBeFalsy();
102+
});
103+
104+
61105
it('should remove scope reference when form with no parent form is removed from the DOM', function() {
62106
var formController;
63107
scope.ctrl = {};

0 commit comments

Comments
 (0)