NVD3 Angular Directive callback firing too soon

angularjs, callback, d3.js, javascript, nvd3.js

Solution

You can also try angular-nvd3 directive. It completely operates with charts via json, and you can also access to the full nvd3 core api.

In your case, you need to somehow refresh the chart.

1). One can use an `api` attribute of this directive like:

//in html
<nvd3 options="options" data="data" api="api"></nvd3>  

and then in controller you can completely refresh directive anywhere using:

//javascript
$scope.api.refresh();

2). Another approach is to just make your chart hidden/visible, using `config` attribute and varying `visible` option like:

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

For example, if there is no data yet, set `visible: false`. While data is returned, set `visible: true`. See live example below.

3). And the simplest way is to just change your data, and directive automatically will be refreshed with new data:

//javascript
$scope.data = newData;
$scope.$apply();  //sometimes you need to refresh the scope

As for your case with ajax it can look something like:

//ajax request; in the live example below I use timeout 
$http.get("/some_url/")
     .success(function(data){
          $scope.data = data;
          $scope.$apply();
          //chart will render after the data returns
     })

Callback function is defined as any other options:

//javascript, in controller
$scope.options = {
    ..., //any other options
    callback: function(){
        d3.selectAll(".nv-bar").on('click', function(){
            alert("Hi, I'm callback!");
        });
    }
}

So it will be fired after chart renders, and after data is returned.

See live example. (updated with callback)

Problem

I've recently started using NVD3's great angular directives for constructing D3 charts. Indeed they are slick. However I'm having a lot of difficulties with callbacks. Callbacks work well enough when I add them using nv.addGraph(), like in Alex's answer and in the examples page. I've also had varying success with other suggestions in these SO answers. But to make it easier for other junior programmers in my company, I would like to use an HTML directive like those shown on the examples on github. Something like this: ``` <nvd3-multi-bar-chart data="monthData" id="monthDataChart" ... other properties ... callback="monthCallback"> <svg></svg> </nvd3-multi-bar-chart> ``` The function in my scope called monthCallback attempts to attach attributes, such as titles, and events, such as click, to each .nv-bar in the chart. The problem is that the chart starts to render before the data returns from the ajax request, and so monthCallback is fired before there are any .nv-bar on the page. (Note: it doesn't seem to make a difference whether or not the callback is declared with parentheses, i.e. callback="monthCallback" vs. callback="monthCallback()") I considered using the workaround by liptga, or DavidSouther's answer, but linking the callback to the transition seemed the wrong way to address this problem. Any other suggestions for getting the callback to fire at the right time, using the HTML directive?

Original source

Related problems