Fun with AngularJS Directives, Isolate Scope and two-way binding

I have a directive defining a component that is reused in a number of views.

I have a view in my app that needs 2 instances of this component.  I also need the two instances to be in sync and behave as one.*

In order to create this illusion, I have defined an object in my view’s controller that will hold the pieces of data needed for the two instances of the component to be able to appear as a single entity.  I pass that object to the directive’s isolate scope with**:

scope: {
  data: '='
}

My component has a couple of functions that manipulate the data object.  These work as expected. I can add and remove properties with the object and both components backed by the object behave as I would expect.

One piece of functionality of this component is CLEARING all of the properties that have been added to the data object.

Of course, the fastest, easiest, and most efficient way to clear the data object is to simply assign an empty object:

$scope.clear = function() {
   $scope.data = {}
}

The alternative of iterating through each key and removing it is obviously not as amazingly time-efficient.

HOWEVER, the two-way binding does NOT work with this assignment.

I repeat: DOES NOT

  1. Adding a property (name: ‘bob’) to the data object
    In the console, I pause the debugger in BOTH the component.js and the controller.js to find that each time $scope.data is the following value:

    { name: 'bob' }
  2. After running in clear(), in the console, I pause the debugger in the component.js and it reports that $scope.data is the following value:
    {}
  3. However, pausing the debugger in controller.js reports that $scope.data is the following value:
    { name: 'bob' }

 

My first thought was “Of course! The isolate scope must have an address it’s watching that was updated when I assigned {} and the controller’s scope did not get that memo and is still looking at an old addy”

Is that true?

I’m not sure. The jury is still out and research is still being done (should you have a definitive answer I’d love to hear it)

Meanwhile, here’s some EXCELLENT info I found on Isolate Scope in Angular:

  1. Isolate-Scope Two-Way Binding is not simply an object reference. The magic is created through angular’s $watch functionality and is *eventually* consistent
    https://www.bennadel.com/blog/2726-isolate-scope-two-way-data-binding-is-eventually-consistent-in-angularjs.htm
  2. $watch() and $watchCollection differences:
    https://www.bennadel.com/blog/2566-scope-watch-vs-watchcollection-in-angularjs.htm
    I was a bit surprised the “rebuild” worked in all cases. I thought perhaps that would clearly define why my situation occurred, but I do not think so after watching that demo.

*Decisions made over two years ago and new designs without the time for a complete refactor gave birth to this situation in the first place.
**This example was simplified

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s