-
Notifications
You must be signed in to change notification settings - Fork 27.3k
fix(ngModel): remove reference to parentForm from removed control #12418
Conversation
@@ -168,6 +168,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { | |||
}); | |||
|
|||
arrayRemove(controls, control); | |||
control.$$parentForm = nullFormCtrl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a similar change is needed in $addControl()
: control.$$parentForm = form
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems right
Since nested Note, that this issue does not only affect validity states, but other properties or forms/controls, such as It would also be nice to have more thorough testing (testing those other properties - not only But other than the comments above, it LGTM 😄 |
(And of course, there is the fail on Travis, but it's an easy fix 😛) |
@gkalpak Thanks for the review! Do you remember what failure Travis recorded? It's such a pain to look through the logs. |
|
@@ -19,7 +19,6 @@ describe('ngModel', function() { | |||
}; | |||
|
|||
element = jqLite('<form><input></form>'); | |||
element.data('$formController', parentFormCtrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the parentFormCtrl is now extracted via regular require, this mechanism doesn't work anymore. This might break people's tests if they relied on the same technique. Are we okay with this?
Thanks @caitp |
27897bb
to
441ac05
Compare
efffd1f
to
8f32876
Compare
|
||
control.$$parentForm = form; | ||
|
||
forEach(control.$pending, function(value, name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this may not be a big deal in most cases, but 3x forEach()
calls seems like a perf hit, which would be most noticeable in forms with visibility controlled by ng-if or ng-switch. I'm not saying it's a huge problem, but yeah
apart from 1 comment, 3rd commit looks ok to me |
} | ||
|
||
if (control.$submitted && !form.$submitted) { | ||
form.$setSubmitted(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really want this ?
It is really a corner case, but if we already have unsubmitted form (with more fields/child-forms), then adding a submitted child-form shouldn't necessarily mark the form as submitted.
(The same holds for a submitted form and unsubmitted child-form being added.)
Neither way seems intuitive (so maybe it's better to leave the property untouched).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is in accordance to what happens in $setSubmitted()
(where the parent form is also marked as submitted), but it feels unintuitive.
Anyway, since this is how things are, let's leave it as is.
@@ -204,7 +224,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { | |||
delete object[property]; | |||
} | |||
}, | |||
parentForm: parentForm, | |||
parentForm: form.$$parentForm, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This property is not used, since you are accessing the parent form via ctrl.$$parentForm
inside addSetValidity()
.
95afb91
to
c2be9f7
Compare
Thanks for the review @gkalpak, I have fixed the cases where the wrong parent was referenced. |
changeInputValue(input, 'a'); | ||
|
||
expect(form.$error.maxlength).toBeFalsy(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this test you are not actually testing that the form has reacted to changes in the added control.
After you add the control you only check form.$error.maxlength
(which hasn't changed since the last time you checked).
Apart for a couple of nitpicks in tests, it LGTM 👍 |
3b80047
to
3a1c446
Compare
…forms This delegates setting the control's parentForm to the parentForm's $addControl method. This way, the model controller saves one instance of looking up the parentForm controller. The form controller keeps two lookups (one for its own ctrl, one for the optional parent). This also fixes adding the parentForm in the following case: - a control is removed from a parent, but its corresponding DOM element is not destroyed - the control is then re-added to the form Before the fix, the control's parentForm was only set once during controller initialization, so the the parentForm would not be set on the control in that specific case.
This fixes cases where the control gets removed, but the control's element stays in the DOM. Previously, if the removed control's validity changed, a reference to it would again be stored on its former parent form. Fixes angular#12263
Test that re-added controls propagate validity changes to the parent form. Ensure that when a form / control that was removed and then attached to a different parent, is renamed / deleted, the new parent will be notified of the change. Document that dynamic adding / removing of controls may require manually propagating the current state of the control to the parent form.
3a1c446
to
cc55ce8
Compare
Otherwise, once the removed control's validity changes,
it will continue to be reflected on its former parent form.
Fixes #12263
@gkalpak can you take a look?