3

I have a directive that looks like this (irrelevant parts omitted):

app.directive('rgReportContainer', function() {
  return {
    restrict: 'E',
    scope: {
      projectIds: '='
    },
    controller: controller
  };

  controller.$inject = ['$scope'];

  function controller($scope) {
    $scope.$watch('projectIds', function(projectIds) {
      console.log(projectIds);
    });
  }
});

The value for projectIds starts off as [], and so the first thing that's logged is [], as I would expect.

What's confusing is that projectIds is populated after a moment by an XHR request, but the value is never picked up.

My template looks something like this:

{{ reports.included_project_ids }}
<rg-report-container project-ids="reports.included_project_ids"></rg-report-container>

I can see in the template that reports.included_project_ids goes from being empty to not-empty. There's a point at which I can plainly see that reports.included_project_ids has data, but at that point, my $scope.$watch isn't picking up the new value.

Any help is very much appreciated.

Jason Swett
  • 43,526
  • 67
  • 220
  • 351

1 Answers1

2

I figured it out. It's because in my controller I was populating reports.included_project_ids by doing

reports.included_project_ids.push(project.id);

Apparently push does not trigger $watch.

Once I switched it to something like the following, it worked.

var projectIds = [];
projectIds.push(project.id);
reports.included_project_ids = projectIds;

Edit: I realized that my problem was due to the fact that $watch doesn't "deeply" check for equality/inequality by default. In order for $watch to work properly for arrays, you have to pass true as the third argument to $watch.

Here's the function signature for $watch form the docs:

$watch(watchExpression, listener, [objectEquality]);

So I decided to leave my original push code and change my $watch to this:

$scope.$watch('projectIds', function(projectIds) {
  console.log(projectIds);
}, true);

That works.

Jason Swett
  • 43,526
  • 67
  • 220
  • 351
  • 1
    I have used $watchCollection when listening for array changes, especially adding/removing items. You can get a brief review of the differences between it and a deep $watch here http://stackoverflow.com/questions/26535415/angularjs-watch-vs-watchcollection-which-is-better-for-performance – edo.n Nov 23 '16 at 15:38