Why don't the AngularJS docs use a dot in the model directive?
Asked Answered
R

4

70

In the video AngularJS MTV Meetup: Best Practices (2012/12/11), Miško explains "..if you use ng-model there has to be a dot somewhere. If you don't have a dot, you're doing it wrong.."

However, the very first example (The Basics) in the Angular.JS website seems to contradict it. What gives? Has Angular.JS changed since the MTV meetup that it's now more forgiving with ng-model?

Rupert answered 12/7, 2013 at 3:14 Comment(2)
I personally think this is more like a philosophy problem about modeling a system. Some people use $scope as a view model, and other people don't. It is a matter of preference.Highwrought
See #15624198Kosse
B
108

That little dot is very important when dealing with the complexities of scope inheritance.

The egghead.io video "The Dot" has a really good overview, as does this very popular stack overflow question: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

I'll try to summarize it here:

Angular.js uses scope inheriting to allow a child scope (such as a child controller) to see the properties of the parent scope. So, let's say you had a setup like:

<div ng-controller="ParentCtrl">
    <input type="text" ng-model="foo"/>
    <div ng-controller="ChildCtrl">
        <input type="text" ng-model="foo"/>
    </div>
</div>

(Play along on a JSFiddle)

At first, if you started the app, and typed into the parent input, the child would update to reflect it.

However, if you edit the child scope, the connection to the parent is now broken, and the two no longer sync up. On the other hand, if you use ng-model="baz.bar", then the link will remain.

The reason this happens is because the child scope uses prototypical inheritance to look up the value, so as long as it never gets set on the child, then it will defer to the parent scope. But, once it's set, it no longer looks up the parent.

When you use an object (baz) instead, nothing ever gets set on the child scope, and the inheritance remains.

For more in-depth details, check out the StackOverflow answer

Blew answered 12/7, 2013 at 5:11 Comment(2)
Am I the only one who thinks adding arbitrary container variables is incredibly ugly? I understand why it is a "best practice" but it is so ugly to see random variables containing the stuff that actually matters. I actually tend to avoid this "best practice" for that reason. I don't often run into any issues, because I am mindful of the consequences. I haven't been bitten by this in over a year of intensive angular development.Jillene
@Jillene My rule of thumb is: if it's UI-only (say, visibility state that doesn't rely on a controller or service), then I use a top-level scope variable. But otherwise, everything lives on a controller (with controllerAs and bindToController syntax), or on a service, enforcing the dot.Blew
S
17

Dot will be required when you prototypically inherit one scope from another for example in case of ng-repeat a new scope is created for every line item which prototypically inherits from parent scope. In the basic example there is no prototype inheritance since there is only one scope but if you have a number of child scopes then you will start facing the problem. The link below will make everything clear.

https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-repeat

Shag answered 12/7, 2013 at 5:8 Comment(0)
K
0

So to solve this, make sure in the JS you declare the parent first:

e.g.

$scope.parent

followed by:

$scope.parent.child = "Imma child";

doing just the child without the parent will break Angular.

Kimberleykimberli answered 24/1, 2017 at 12:42 Comment(0)
R
0

According to @OverZealous's answer, I thought up a dirty but comfortably simple and quick workaround for this:

$scope.$s = $scope
$scope.foo = 'hello'

Then use $s in template can safely modify model:

<input ng-model="$s.foo"/>

I wrote a service for such dirty works in my project.

Ranged answered 17/7, 2020 at 10:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.