1

It is a strange issue not only about nvd3 directive, I have steped into the directive source code, but still not find the reason.
I put it in plunker, switch comment line 34 and 35 in app.js will show the issue.
if I set a new value in $scope.data, the chart works well, but if I set a newData, the chart will not work.
I've debug the angular-nvd3 directive, when I change the whole data object, the $watch('data') (angular-nvd3.js line 320) still work, but the scope.chart.update() not working correct. I didn't found anywhere that nvd3.js hold the chart data, so I really don't know what happend, why not working....

Any comment will be a preciate!

Awakening
  • 3,615
  • 8
  • 35
  • 51

2 Answers2

3

I believe this is a quirk of how nvd3 is using d3 data-binding.

The initial data array is bound to the DOM like a standard d3 visualization and holds a reference to it. When you modify the array in the directive, it triggers a redraw and since it's the same array (reference to it), the bound data is changed and the plot redraws normally.

When you change the array after the first draw, under the hood, the array that still data-binded is the initial array (the one with no data). The directive still triggers a re-draw but with no data.

To do what you want, instead of calling $scope.$apply(); get api into the $scope with:

<nvd3 options="options" data="data" api="api" config="{refreshDataOnly: true}"> </nvd3>

and then use:

$scope.api.updateWithData($scope.data);

Updated example.

Mark
  • 106,305
  • 20
  • 172
  • 230
  • Hi Mark, thanks for making the chart work, but there going to have another issue, Do you see the chart flash when `$scope.api.updateWithData($scope.data);`? The chart seems to remove and re-create, not like the previous one - with a smoothly animate to change to the newData – Awakening Jun 08 '15 at 00:00
  • @Awakening, I don't see an easy way to fix that, from looking at the `nvd3` examples, it looks like a re-bind means a complete re-draw. The bigger question here, is why do you need to "replace" the `$scope.data`? What use case do you have where you just can't replace the contents of it? – Mark Jun 08 '15 at 12:53
  • I think it is a very common situation, When you get a new data from server, you need to replace the $scope.data like `$scope.data = newData` – Awakening Jun 10 '15 at 01:42
  • @Awakening, yes I understand that but instead of replacing the array just change the contents of the array. – Mark Jun 10 '15 at 23:11
  • 1
    $scope.api wont work for me. api seems to be undefined. I'm not able to find anything online to fix this. When I start with an empty array of data and later point to a new array, the chart wont refresh. – icedek Feb 18 '16 at 03:45
2

Since the version 1.0.2 you might also want to set deepWatchData as true. There was a commit on 15/09/2015 and now this option by default is false which means that Angular's watch expression will not track changes in array with data.

No need in doing scope.api.refresh() with this settings. No need in rewriting of the whole array of data, with new portion of data you just add/push it to array. This will help to prevent flashing when reassigning new data.

Now instead of: <nvd3 options="options" data="data" class="with-3d-shadow with-transitions" config="{refreshDataOnly: true}"></nvd3>

should be: <nvd3 options="options" data="data" class="with-3d-shadow with-transitions" config="{refreshDataOnly: true, deepWatchData: true}"></nvd3>

Valera Tumash
  • 628
  • 7
  • 16
  • It's not working for me. I have done the same. angular-nvd3: "1.0.9". Is there anything that is changed after this release..? – Riken Mehta Oct 07 '17 at 06:09