user944513
user944513

Reputation: 12729

why ng-model behave unexpectedly in angularjs?

I take two example in angular js but I am getting unexpected result .Example of nested controller :

First example

<div ng-controller="maincontroller">
        <input ng-model="data.name">
         <h1>{{data.name}}</h1>

        <div ng-controller="nestedcontroller">
            <input ng-model="data.name">
             <h1>{{data.name}}</h1>

            <div ng-controller="nestedANOTHERcontroller">
                <input ng-model="data.name">
                 <h1>{{data.name}}</h1>

            </div>
        </div>
      <div ng-controller="nestedOUTERRcontroller">
                <input ng-model="data.name">
                 <h1>{{data.name}}</h1>

            </div>
    </div>

when I take "data.name" in all nested controller .Now when I change any input field it reflect in all input field and header field.why ?

Secondly when I take "name" instead of "data.name"

 <div ng-controller="maincontroller">
            <input ng-model="name">
             <h1>{{name}}</h1>

            <div ng-controller="nestedcontroller">
                <input ng-model="name">
                 <h1>{{name}}</h1>

                <div ng-controller="nestedANOTHERcontroller">
                    <input ng-model="name">
                     <h1>{{name}}</h1>

                </div>
            </div>
          <div ng-controller="nestedOUTERRcontroller">
                    <input ng-model="name">
                     <h1>{{name}}</h1>

                </div>
        </div>

when I change on top input field it change in all input field and header field.but when i move to second input field it change to it's nested(children) input field and header but not change to upper controller and sibling controller why ? and when I move to inner most controller and change the text inside the input field it show header .Now if it parent controller try to change its text it it is not able to do .parents controller now change its only its text why ?

here is my code http://codepen.io/anon/pen/xGGJKR

Thanks

Upvotes: 0

Views: 134

Answers (2)

New Dev
New Dev

Reputation: 49590

This has to do with how scope inheritance works. For a more comprehensive answer on nuances of scope inheritance, read this SO answer.

First, you have to recognize that ng-controller directive creates a child scope that prototypically inherits from the parent, and so you have nested scopes here of the following hierarchy (the numbers are $ids of each scope)

  #2
 /  \
#5  #3
      \
      #4

So, when you type something in the first <input> it will create $scope.data = {name: "foo"} in scope #2 and will be inherited (visible) by all the nested scopes. On the other hand, if you type in the second <input> - then it will create $scope.data (as above) in scope #3, but neither #2 nor #5 will inherit it.

Second point has to do with setting the value when you use data.name vs name. Again, this has to do with nuances of prototypical inheritance.

When ng-model sets the variable data.name, it writes into the inherited data object under name property - as expected - wherever data was defined. In other words, the data object is read (and thus the inherited object is read) and the name property is written into.

When, however, ng-model sets the variable name, then it will write directly into the property name of the current scope, thus shadowing the inherited name property from the parent.

The proper approach is:

  1. always to use a dot (.) notation with ng-model (or any two-way bound attributes).
  2. define the data object based on where you want it to be - don't leave it up to the ng-model to define. For example (if this is the intent), define it in the maincontroller:

    .controller("maincontroller", function($scope){
       $scope.data = {};
    });
    

    The effect of that would be that all the inputs would be bound to the same property.

Upvotes: 1

shaunhusain
shaunhusain

Reputation: 19748

The short answer is prototypical inheritance of the scope properties (don't use the scope as your model instead create a reference to your model from some property of the scope). Typically use a service or a factory or some other provider definition to store the model and do most of the work and just use the controller to make the appropriate providers and data available to the view.

https://youtu.be/ZhfUv0spHCY?t=31m12s

What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

Upvotes: 0

Related Questions