Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(ngModelOptions): work correctly when on the template of replace directives #15493

Closed

Conversation

gkalpak
Copy link
Member

@gkalpak gkalpak commented Dec 11, 2016

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix.

What is the current behavior? (You can also link to an open issue here)
In order for ngModel and ngModelOptions to work correctly together, the latter's pre-linking function should be run before the former's pre-linking function. This is typically what happens, except when ngModel is used on an element which also has a replace directive, whose template includes ngModelOptions. In that case, the order is reversed.
See #15492 for more details.

What is the new behavior (if this is a feature change)?
The initialization logic of ngModelOptions is moved from its pre-linking function to its controller's $onInit() lifecycle hook. This way, it is always guaranteed to be run before ngModel's pre-linking function, even in the replace scenario mentioned above.

Does this PR introduce a breaking change?
Maybe.
There is no breaking change wrt 1.5.x (where the initialization of ngModelOptions used to take place in the controller itself), but wrt to 1.6.0 the following usecase will no longer be possible:
A sibling directive to ngModelOptions, let's call it foo could be modifying the model options definition (e.g. ng-model-options="modelOptionsDefinition") in its $onInit() lifecycle hook. If the foo directive had a lower priority that ngModelOptions, then it will no longer work after this PR, since its $onInit() method will be called after ngModelOptions is initialized.
(This can be worked around by changing the priority of foo to be higher than ngModelOptions or by overwriting ngModelOptions#$options from foo#$onInit().

Please check if the PR fulfills these requirements

Other information:
Fixes #15492.

… directives

Previously, in order for `ngModel` and `ngModelOptions` to work correctly
together, the latter's pre-linking function should be run before the former's
pre-linking function. This was typically what happened, except when `ngModel`
was used on an element which also had a `replace` directive, whose template
included `ngModelOptions`. In that case, the order was reversed.

This commit fixes it by moving the initialization logic of `ngModelOptions` from
its pre-linking function to its controller's `$onInit()` lifecycle hook.

Fixes angular#15492
@petebacondarwin
Copy link
Contributor

On the surface I like the look of this! I need to spend some time tomorrow checking it.

Copy link
Contributor

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor naming suggestion but LGTM.
Good fix @gkalpak

optionsCtrl.$options = parentOptions.createChild(scope.$eval(attrs.ngModelOptions));
}
}
require: {parentOptionsCtrl: '?^^ngModelOptions'},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reason why I moved it to the pre-link function is because this feature of requiring directly onto the controller was either not available or very new.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC this is the first occurrence of this feature in Angular's codebase 🏋️

}
NgModelOptionsController.prototype = {
$onInit: function() {
var parentCtrl = this.parentOptionsCtrl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that we can name the binding anything we like why not just call it parentCtrl and then there would be very little motivation for this line any more.

@gkalpak gkalpak closed this in ce8abac Dec 12, 2016
gkalpak added a commit that referenced this pull request Dec 12, 2016
… directives

Previously, in order for `ngModel` and `ngModelOptions` to work correctly
together, the latter's pre-linking function should be run before the former's
pre-linking function. This was typically what happened, except when `ngModel`
was used on an element which also had a `replace` directive, whose template
included `ngModelOptions`. In that case, the order was reversed.

This commit fixes it by moving the initialization logic of `ngModelOptions` from
its pre-linking function to its controller's `$onInit()` lifecycle hook.

Fixes #15492

Closes #15493
@gkalpak gkalpak deleted the fix-ngModelOptions-with-replace branch December 12, 2016 22:15
ellimist pushed a commit to ellimist/angular.js that referenced this pull request Mar 15, 2017
… directives

Previously, in order for `ngModel` and `ngModelOptions` to work correctly
together, the latter's pre-linking function should be run before the former's
pre-linking function. This was typically what happened, except when `ngModel`
was used on an element which also had a `replace` directive, whose template
included `ngModelOptions`. In that case, the order was reversed.

This commit fixes it by moving the initialization logic of `ngModelOptions` from
its pre-linking function to its controller's `$onInit()` lifecycle hook.

Fixes angular#15492

Closes angular#15493
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ng-model-options in a template of component makes error in angular 1.6.0
3 participants