Skip to content

Instantly share code, notes, and snippets.

@reicolina
Last active May 10, 2017 21:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reicolina/7b6af6f1ed1d815fe03c to your computer and use it in GitHub Desktop.
Save reicolina/7b6af6f1ed1d815fe03c to your computer and use it in GitHub Desktop.
AngularJS and why you need one or more “dots”

In Angular, it is recommended to add objects to a scope instead of primitive values (always having one or more “dots” when accessing your models)

The reason is: prototypical inheritance. As you know, Javascript is different from classical OOP; inheritance is done in a prototypical matter. Angular follows this pattern in a way that scopes inherit prototypically from their parent scopes.

When implemented incorrectly, two-way data binding breaks if you have two or more nested elements that use separate controllers that point to the same model. Here is why:

Imagine you have two nested elements:

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

The child scope looks for “foo” up the prototypical chain if not present in ChildCtrl, so two-way binding works here. However, if you type anything on the second “child” input, then you are basically doing $scope.foo = “something” which creates the foo object in the child scope. Now the prototype chain is not “consulted” when accessing “foo” as the child scope will have its own, hence, the binding is broken.

Now, if we use objects instead of primitives, and do something like this:

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

When changing the value of the child input field you will be doing: $scope.baz.foo = “something”. In this case you won’t be changing the “baz” object, you are only assigning a value to its property; therefore, the prototype chain is consulted up to the parent scope, which maintains the 2-way binding.

In summary, you should be OK as long as you don’t directly change an object that belongs to a scope, but instead, change the object's properties. In other words: “if you use ng-model there has to be a dot somewhere."

In think that Angular should print a warning to the browser’s console when things like this happens, as the documentation is not that clear and this scenario causes a lot of confusion for developers (and bugs), but hey..it’s probably easier said than done ;-)

I hope this helps understand the root of this very common problem that we encounter with Angular more often than not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment