23

I am using nvd3.js and trying to add a click event

d3.selectAll(".nv-bar").on('click', function () {console.log("test");});

JSFiddle

How can I do that ?

VividD
  • 10,040
  • 6
  • 59
  • 107
Petran
  • 6,715
  • 17
  • 53
  • 89
  • My previous answer has a fault so had to delete it, did not notice that, will get an answer as soon as I can, or someone else will post an answer before that, sorry about it. – shabeer90 Jul 12 '13 at 09:49

11 Answers11

41

Just found out that this works as well (at least for multibar charts):

chart.multibar.dispatch.on("elementClick", function(e) {
    console.log(e);
});

I had to look at the source in src/multibar.js to find out; since it's there, I guess this is the way it was intended to be done. However, I second what Alex said in his answer: the lack of documentation for NVD3 is a really big disadvantage. Which is sad because the general idea of the project is great: giving us the power of D3 without going into all the details...

wexman
  • 1,036
  • 8
  • 17
  • 4
    This works well. You just have to match the object to your chart type: `chart.pie`, `chart.bars`, `chart.lines`. – iamsar Apr 14 '14 at 15:03
  • This is very useful. Thanks! – Nikhil Sep 11 '14 at 11:03
  • 3
    Very frustrating that the most recent release (1.8.1) no longer returns the event or the series of data, only the bar (or circle), which is a huge pain point if you were using the `d3.event` to grab the element and style it, e.g change the bar's color. See https://github.com/novus/nvd3/blob/v1.8.1/build/nv.d3.js#L4946 vs. https://github.com/novus/nvd3/blob/v1.7.1/build/nv.d3.js#L3745 – Aleck Landgraf Oct 29 '15 at 00:02
  • Looking at the source for each model is really useful. Generally, if there's a clickable/interactable element in the chart, the source will show the way to get access to that event with a function, even if there isn't specifically a callback in the documentation. In my case, I was trying to change the `textContent` of another DOM node according to what data streams were selected. – Escher Jan 02 '16 at 14:55
  • I've only tried with line chart's lines, but it seems like e contains all data for the entire chart, instead of only the one series of line that I click on, which loses the entire point of this click event; I want to know which line I've clicked on. After some more testing I've figured out that this is probably a bug on nvd3's side, which, whenever `useInteractiveGuideline` is also turned on for the graph, we are unable to retrieve which specific line is clicked. – Haonan Chen Jul 10 '17 at 08:22
31

I was running into the same issue and was about to dump NVD3 all together because of the lack of documentation... What you need to do is add a callback function to addGraph(). Also note the d3.selectAll() instead of d3.select().

Good Luck.

nv.addGraph(function() {
     var chart = nv.models.multiBarHorizontalChart()
         .x(function(d) { return d.label })
         .y(function(d) { return d.value })
         .margin({top: 5, right: 5, bottom: 5, left: 5})
         .showValues(false)
         .tooltips(true)
         .showControls(false);

     chart.yAxis
         .tickFormat(d3.format('d'));

     d3.select('#social-graph svg')
         .datum([data])
       .transition().duration(500)
         .call(chart);

       nv.utils.windowResize(chart.update);

       return chart;
     },function(){
          d3.selectAll(".nv-bar").on('click',
               function(){
                     console.log("test");
           });
      });
Alex
  • 396
  • 3
  • 8
  • 3
    unfortunately i had no luck applying this approach to a nv3d line chart. my goal was to get the data of the clicked line point (x,y), but d3.selectAll("nv-point-paths")on('click') gave me the data of the whole chart instead of the individual point. I hoped to fix this with d3.selectAll("nv-point-paths path").on('click'), but this handler never triggered. Any idea? – fbuchinger Dec 13 '13 at 13:04
  • Actually if you take a look at the examles, you will see that the best way to handle events is what wexman suggested. – Gábor Lipták Feb 19 '14 at 14:59
  • on stacked bar chart , once you change legends , the click events disappear. Its not the case with Wexman's answer though. – sunnyvilles Aug 01 '14 at 11:23
  • 1
    On the function add the param e, and then console.log(e), you'll find data for the selected bar. – Rhys Bradbury Jun 13 '16 at 15:15
4

There are three key points here.

1) No documentation means you have to go through the source code.

2) All graphs have a tooltip, which means events are already firing in the source code.

3) Use the configuration object (in the Documentation) as a road map of the source code.

ie.

var config = {chart: {type: 'multiChart',xAxis:{},yAxis{}}

Open the nvd3/nv.d3.js file

CTRL+F+ the chart type. In this case it is 'multiChart'.

You will see nv.models.multiChart.

Scroll down to find the tooltip events and you will find the needed documentation.

lines1.dispatch.on('elementMouseout.tooltip', function(evt) {tooltip.hidden(true) });
stack1.dispatch.on('elementMouseout.tooltip', function(evt) {tooltip.hidden(true) });
bars1.dispatch.on('elementMouseout.tooltip', function(evt) {tooltip.hidden(true) });

Therefore, to write your own event...

var config = {chart: {type: 'multiChart',
               bars1: {
                dispatch:{
                    elementClick:function(e){//do Stuff}
                },
               xAxis:{},yAxis{}
              }
Jed Lynch
  • 1,457
  • 14
  • 9
2

This worked for me: (e.target.data outputs the data attributes attached to that element, like x, y)

$(document).on("click", "#chart svg", function(e) {
     console.log (e);
     console.log (e.target.__data__);
    });
Cliff Coulter
  • 337
  • 5
  • 20
2

If using AngularJS, use this code in your app.js.

$scope.$on('elementClick.directive', function(angularEvent, event){
    console.log(event);
});
J0e3gan
  • 8,287
  • 9
  • 48
  • 76
2

This coderwall blog heads us the right direction.

chr.scatter.dispatch.on('elementClick', function(event) { console.log(event); });

Tibi02
  • 643
  • 7
  • 14
2

This worked for me. https://bridge360blog.com/2016/03/07/adding-and-handling-click-events-for-nvd3-graph-elements-in-angular-applications/

Just use console.log(e) instead of console.log(e.data) to avoid undefined error.

Disha teli
  • 41
  • 3
0

jQuery makes this easy:

$( ".nv-bar" ).click(function() {
  console.log("test");
});

Fiddle @ http://jsfiddle.net/eTT5y/1/

pmont
  • 1,994
  • 19
  • 41
0
$('.nv-pie .nv-pie .nv-slice').click(function(){
   temp = $(this).text();
   alert(temp);
})

This would work fine for the Pie Chart ,Similarly u can go ahead for other charts too....

itsaruns
  • 499
  • 2
  • 9
  • 16
0

For stacked area chart, you should disable interactiveGuideline and use elementClick.area:

chart.useInteractiveGuideline(false);

chart.stacked.scatter.dispatch.on("elementClick.area", function(e) {
  console.log(e);
});
Saeid
  • 483
  • 5
  • 14
0

Just add callback to you options in controller If using BarChart then replace multibar to discretebar

$scope.options = {
chart: {
    type: 'multiBarHorizontalChart',
    height: 450,
    x: function(d){return d.label;},
    y: function(d){return d.value;},
    showControls: true,
    showValues: true,
    duration: 500,
    xAxis: {
        showMaxMin: false
    },
    yAxis: {
        axisLabel: 'Values',
        tickFormat: function(d) {
            return d3.format(',.2f')(d);
        }
    },
    callback: function(chart) {
        chart.multibar.dispatch.on('elementClick', function(e){
            console.log('elementClick in callback', e.data);                             
        });
    }
}
};
Sunil Jakhar
  • 119
  • 6