I'm new to Angular, so I'm trying to follow tutorial and just don't get it.What confuses me is the dot notation:
<div ng-app="">
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>
<div ng-controller="FirstCtrl">
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>
</div>
<div ng-controller="SecondCtrl">
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>
</div>
</div>
Typing a value inside any of the input boxes will update all the other input boxes.
So, what I think that is going on here is that the first ng-model
declaration outside controllers is binding the input element value to the data.message model in the root scope.I don't understand how the bindings inside ng-controller
are then reading the value from the root scope, and why values inserted inside ng-controller
scope will be shown in a input box outside that scope?
Also if data.
is removed
<div ng-app="">
<input type="text" ng-model="message">
<h1>{{ message }}</h1>
<div ng-controller="FirstCtrl">
<input type="text" ng-model="message">
<h1>{{ message }}</h1>
</div>
<div ng-controller="SecondCtrl">
<input type="text" ng-model="message">
<h1>{{ message }}</h1>
</div>
</div>
that behavior is gone, how come?
Your first example is the recommended way to do things in Angular. The best practice being that there should always be a dot in your ngModel
s as using primitives in an ngModel
is a common source of bugs in Angular.
This is discussed at length in Angular's understand scopes document:
This issue with primitives can be easily avoided by following the
"best practice" of always have a '.' in your ng-models – watch 3
minutes worth. Misko demonstrates the primitive binding issue with
ng-switch.
But in short this is due to how Javascript's prototypal inheritance works.
In your second example you have a primitive type - a string for example- inside each ngModel
. When the ngModel
in each controller (each on their own child scopes) tries to read from a primitive type they look to their parents first to see if the variable is there. If it is then they read from it. However when one of the ngModels
writes to that primitive then a new instance of the primitive is added on it's scope.
Thus each input
shares a common variable (the one on your top scope) at first, when only being read from, and then each input
switches to using an independent variable once it's written to. You can watch this in action in this fiddle by first typing in the top, parent, input
and then in the children.
Angular recommends avoiding this since the mismatch between how reading and writing operate can clearly be very confusing and error prone
In your first example you're instead creating an object data
with a property message
. In this case reading works just like with a primitive- it looks to find that object with that property on the parent scope and reads from it if it's there. But this time writing works the same way as reading- if there is a parent object data
with property message
then the write is done to the object's property.
So, when you use dot notation, reading and writing act consistently as you can see in this fiddle
In the first code, data
as an object is a common object between three scopes and each scope has reference to data.So when data.message
is changed all three scope show the changed message.
But in the second case the message
is a string witch is a value type not an object. Each scope has its own message and changing one of theme will not effect others.