5
votes

Whenever I click on one of the points it causes the chart to update. This only happens if I've got an ngClick directive on the <nvd3> element (even if the listener function does nothing). If I remove the ngClick, everything's fine.

I'm using a pretty basic nvd3 scatter chart with angular-nvd3.

What could be causing this strange interaction?

(The framerate of this recording is low, so it's hard to see but the chart is redrawn on each click, including the top one)

Clicking points on a graph

Here's a plunker that reproduces the issue:

http://plnkr.co/edit/F0ZslBaisoHWIp0VcI8o

Thanks!

UPDATE I've narrowed it down to a watch within angular-nvd3. Somehow the presence of the ngClick is causing the 'data' to change. This line is triggering the refresh: https://github.com/krispo/angular-nvd3/blob/master/dist/angular-nvd3.js#L328 There's nothing in my code that changes 'data' (also verified the object is the same instance outside the directive), and there's nothing I can see in angular-nvd3.js that could change the data at all... hmmm...

UPDATE Here's my click event listener (it's empty):

controller.handleChartClick = function(event) {
};

and html:

<div class="col-sm-10">
    <nvd3 ng-click="observationsCharts.handleChartClick($event)"
              options="observationsCharts.scatterPlotChartOptions"
              data="observationsCharts.scatterPlotChartData"></nvd3>
</div>
2
what are you calling on ng-click?Terafor
Is your data built exactly the same as in the plunkr? There must be something different within your code if the issue doesn't reproduce in the example. Can you post your actual code?Stacey Burns
@StaceyBurns, I updated my question and the plunker, please take a look. Now it reproduces the issue and it also has some of the data I'm using in my production code. The other differences are: I updated the versions of d3, nvd3, and angular-nvd3 in the plunker (the plunker was using old versions and I didn't notice) and I also stripped it down to the minimum code.HankScorpio
@Terafor an empty click handler. Check out the updated question.HankScorpio
this is wired. i guess workaround is to make an absolutely positioned element and use ng-click on that...Terafor

2 Answers

2
votes

You are correct that the following watch is causing the issue:

// Watching on data changing
 scope.$watch('data', function (newData, oldData) {
  if (newData !== oldData && scope.chart) {

    if (!scope._config.disabled && scope._config.autorefresh) {
        scope._config.refreshDataOnly && scope.chart.update ? scope.chart.update() : scope.api.refresh(); // if wanted to refresh data only, use chart.update method, otherwise use full refresh.
                            }
                        }
                    }, scope._config.deepWatchData);

The thing is, if you add a log in this function to see what the old and new data is, the data is actually changing.

When you click on one of the points, nvd3 is adding a color attribute to the data.

old data:

[{"key":"Battery Voltage","values":[{"x":1439419440000,"y":90,"series":0},{"x":1439419440000,"y":43,"series":0},{"x":1439419440000,"y":345,"series":0},{"x":1439167620000,"y":73,"series":0},{"x":1439167620000,"y":42,"series":0},{"x":1439167620000,"y":36,"series":0},{"x":1440010740000,"y":32,"series":0},{"x":1439419440000,"y":62,"series":0},{"x":1439167620000,"y":73,"series":0},{"x":1439167620000,"y":42,"series":0},{"x":1439167620000,"y":36,"series":0}]}] 

new data:

[{"key":"Battery Voltage","values":[{"x":1439419440000,"y":90,"series":0,"color":"#1f77b4"},{"x":1439419440000,"y":43,"series":0,"color":"#1f77b4"},{"x":1439419440000,"y":345,"series":0},{"x":1439167620000,"y":73,"series":0},{"x":1439167620000,"y":42,"series":0},{"x":1439167620000,"y":36,"series":0},{"x":1440010740000,"y":32,"series":0},{"x":1439419440000,"y":62,"series":0,"color":"#1f77b4"},{"x":1439167620000,"y":73,"series":0},{"x":1439167620000,"y":42,"series":0},{"x":1439167620000,"y":36,"series":0}],"color":"#1f77b4","value":90}] 

Each time you click a new point, the color attribute is added to the object, so the watch function is actually running correctly.

I would advise opening an issue over at https://github.com/krispo/angular-nvd3

**Edit - Just to clarify, the reason it happens when ng-click is added is because this forces the Angular digest cycle to run which will trigger the watch.

2
votes

Looks like the only workaround to this (for now) is to use the config setting deepWatchData: false. That prevents the $watch getting triggered too often.

<nvd3 config="{deepWatchData: false}" options="..." data="..."/>