-
Notifications
You must be signed in to change notification settings - Fork 27.5k
ngModelCtrl pollutes child scope #8539
Comments
OK, so this is situation very similar to the one that we had with isolated scopes and that was corrected in b5af198. Here we've got exactly the same situation but for child scopes. Here is a smaller reproduce scenario: http://plnkr.co/edit/yKMzQD?p=preview which shows that it has nothing to do with the $parsers pipeline but it is a child scope that messes up things. It "works correctly" for isolated scopes: http://plnkr.co/edit/3Sdiaq?p=preview I guess we should unify behaviour for isolated and child scopes so this should be seen as a bug. @Izhaki out of curiosity - what is your exact use case? Why do you need to have a child scope in a directive that works alongside ngModel? In any case you can easily work-around it today by creating your child-scope manually: http://plnkr.co/edit/6tlWam?p=preview |
I don't think this is a bug --- the isolate scope doesn't get passed to every directive applied to an element, it's self-contained. The fact that the ng-model controller doesn't use the isolate scope works as expected (but I'm not saying it doesn't confuse people) |
Given the ng-model is set on a directive which has it's own scope, this behavior seems completely accurate. Child scopes don't update parent scopes. For an example see http://plnkr.co/edit/5BVZiEEUWXrF2U6gVbc7 . Note that updating the first input does update the second, but only as long as the second isn't manually updated. |
@FesterCluck I'm not sure what you mean by "ng-model is set on a directive which has it's own scope". There is no such thing as setting ng-model on another directive. What is happening here that both directives are used on the same element and the intuition is that ng-model directive is bound to a different scope than a directive requesting a child scope. This is how it works for combination of ng-model and another directive requesting an isolated scope on the same DOM element. @caitp yeh, I'm not sure if this is a bug or not, I guess I'm more concerned with the discrepancy among directives asking for a child scope and an isolated scope on the same element. Please compare:
The question is this: should a directive asking for a child scope should "force" this scope on ng-model. This used to happen with directives asking for an isloated scope but was changed in b5af198. Unless I'm drawing too many parallels between behaviour of directives asking for an isolated and child scope. In short: should a child scope be self-contained as it is the case for isolated scopes? |
I'm not sure if I'm making myself clear but hopefully this plunk showing 2 situations side-by-side should make it more explicit: http://plnkr.co/edit/6QZfRh?p=preview |
@pkozlowski-opensource Child scopes are not 2 way bound, plain and simple. As soon as the child scope defines a property locally, inheritance is lost. IMHO prototypical inheritance behavior should be retained somewhere, and this is it. After spending a good 2 hours on this I realized how it can be confusing that a single directive can usurp the scope of all directives on an element. However, adding some config property to change this behavior seems moot when isolated scopes can perform the same behavior in a different way. |
The directive in question is a typeahead one introduced on an input element. Reasons for using child scopeThere are three reasons why child scope is used: Complex attributesHistorically (if I can use the term as it was very recent and short lived), the directive received an expression as a config, same as ngRepeat:
Then a parser, like with Object configsThen, as more and more config options were added, the syntax changed to a config object:
Now while you can bind the config object to an isolated scope property:
There is no way to use the native binding for object properties. This throws an error:
Only one isolated scopeThen comes the natural reluctancy to use isolated scopes, as only one can be defined per element. In another directive, I wish to separate the Drag and Drop (DnD) logic from a tree logic, allowing DnD to be used only when needed, something like so:
Now which one of them should get an isolated scope? Both, ideally. But you can't - so to play it 'safe' you use child scope in both. In other words, to make sure a directive works alongside other directive, it is safer to use a child scope. Private scope won't workThe proposal to create a private scope (a manually created child scope) won't work in this case. The directives has the following structure:
With some of the directives below typeahead needing its scope to work (eg, |
Well, it can be well useful if they would, and the directive in question does it manually. See Expose isolated scope binding API. I personally don't see any justifications for binding to be a trait of an isolated scope only - you bind on a scope, so any scope should offer that, isolated or not. |
I believe I understand your claim this works as excepted, particularly if one considers the case of isolated scope (isolated scope works just fine - it's child scopes that don't). As this issue demonstrates, my understanding of scopes is incomplete, although I understand it better now then I did when I filed the referenced issue. But allow me to provide my point of view, if not only for the sake of revealing how others may think how things should work. Consider the following:
Parent scopeNow if Isolated scopeIf If I understand correctly by looking at Child scopeIf The only reason In other words, my argument is that Again, look at the code:
Why should |
Could someone check if this still needs discussing? I believe the core description of this discussion could be "Directive child scopes prototypically inherit from one another with parent scope as the prototype. The behavior of base owned properties can be confusing. Should something be done?" My vote is no and that this issue be closed. |
Seeing as this has been around for nearly 3 years with little activity - closing. |
There seems to be a bug with
ngModelController
$parsers - instead of updating the model (on the parent scope), they create a new property on the local (child) scope. Oddly, this doesn't happen with an isolated scope.With this html (plunk):
And this script:
The actual model value never update on the controller level. Instead, a property called 'appCount' is created on the scope of the directive.
It seems that the issue is on this line (it sets the model on the child scope, not parent scope):
within the following
ngModelController
code:The text was updated successfully, but these errors were encountered: