Juri Strumpflohner

Juri is a full stack developer and tech lead with a special passion for the web and frontend development. He creates online videos for Egghead.io, writes articles on his blog and for tech magazines, occasionally speaks at conferences and holds training workshops.

MOAR dots... Watch out when binding your data. Do you pass it an object reference or a value?

Angular data-binding seems magic, but obviously isn't. You have to give it a chance to do its work. As such, watch out and think about the difference "copy by value" and "copy by reference".

This article is part of my "Learning NG" series, presenting some of my adventures while learning Angular. Check out the series intro and other articles. Something not quite as you think? I'm more than happy for any kind of feedback and improvement suggestions.

The issue

I have a sidebar with the application menu, which is wrapped into its own directive. Furthermore there is a button somewhere else on the application which - when clicked - should toggle the sidebar (hide/show it).

There are different implementation possibilities:

Directly set the state of the sidebar by keeping a reference to it from the button

Have a publisher/subscriber mechanism where the sidebar registers to an event, say “sidebar.toggle” and based on that hides/shows itself

Establish a 2-way data binding with a common object that is known by the sidebar as well as by the button.

Option 1 is good for simple situations (like the menu of my blog here), but I don’t really like it in a more large-scale app. It quickly gets messy as you soon run into the situation where interaction with the menu is needed from multiple parts of the application. Keeping lots of “hard references” quickly complicates the codebase and makes it more fragile. Option 2 solves this by decoupling through events. This works nicely and is a cleaner solution.

There’s a 3rd option, namely to use some shared object which in Angular can be nicely represented by a service. Being a singleton it is an ideal candidate to hook on a 2-way-binding like:

sidebar directive binds to isVisible property defined on the service

button switches on the isVisible property on the service

That’s exactly what I did. The service is quite simple in that it exposes an object containing the current state.

As you can see it doesn’t really work as expected. What’s going on here? Even though there’s a lot of “magic” involved in how Angular realizes 2-way data binding, you have to give it a minimum chance keep track of what happens.

If you take a look at my code above, you can see that I directly bind the boolean property of the service to my $scope:

Solution

The problem here is that the isVisible property on the $scope obviously won’t get updated as there is no connection to the one defined on the service object. Since booleans are a values types, simply the value is copied over. Hence, they don’t reference the same OBJECT.

Thus, what I have to do instead, is to bind an object instance onto the $scope.

In this way, $scope and service point to the same object instance and hence the digest loop can watch the object to update the HTML accordingly:

Apparently this seems to be a common issue with Angular newbies as I encountered other devs on the IRC chat having similar problems. Response from the experts: “MOAR dots..” :)

...
[10:25:37] <denny009> hello all. I've a directive that inside do scope.$new() and it works well (create a json tree). The problem now is that I want communicate with the parent. The first time the communication works well but the second when the scope change I lost it
...
[10:28:21] <Grokling> denny009: MOAR dots..
...
[10:28:44] <denny009> Grokling: sorry?
[10:30:20] <denny009> Grokling: what mean "MOAR dots"
...
[10:31:14] <Grokling> denny009: Javascript passes objects by reverence, and primitives by value. You have a primitive 'jsonData' there, so you're copying the value, and it has no reference to any new value you might replace it with.
...
[10:35:02] <Grokling> denny009: You should always have a dot in your bindings (hence: MOAR dots). sendrequest(thing.request) would be an example.
```