1

I have a React component that renders a chart using Dygraphs. I want to hide the series when I click on it's label.

createGraph() {
  this.g = new Dygraph(
      this.refs.graphdiv,
      this.state.options.data,
      {
        strokeWidth: 1,
        labels: this.state.options.labels,
        drawPoints:true,
        stepPlot: true,
        xlabel: 'Time',
        ylabel: 'Metric value',
        legend: 'always',
        connectSeparatedPoints: true,
        series: this.state.options.series,
        labelsDiv: "labels",
        legendFormatter: this.legendFormatter
      }
  );
}

render() {
return (
  <div>
    <h2>Time series for system {this.props.sysId.replace(/_/g, ':')}</h2>
    <h3>{this.props.date}</h3>
    <div id="graphdiv" ref="graphdiv" style={{width: window.innerWidth - 50, height: window.innerHeight - 200}}></div>
    <p></p>
    <div id="labels"></div>
  </div>
);
}

To do this I have implemented the dygraphs callback "legendFormatter" and created the labels with a onClick callback:

legendFormatter(data) {
    if (data.x == null) {
        // This happens when there's no selection and {legend: 'always'} is set.

        let f = () => {
            data.dygraph.setVisibility(0, false);
            data.dygraph.updateOptions({})
        }

        // return '<br>' + data.series.map( (series) => {
        //   return series.dashHTML + ' ' + "<label onclick='f();'>" + series.labelHTML + "</label>"
        // }, this).join('<br>');
        
        let x = data.dygraph;

        return '<br>' + data.series[0].dashHTML + ' ' + "<label onclick='console.log(x);'>" + data.series[0].labelHTML + "</label>"
 }        

The problem is that I cannot access the "this" from React nor I can access the variables in the legendFormatter function:

f() is undefined

x is undefined

How can I bind the context to the onClick function?

Community
  • 1
  • 1

2 Answers2

0

You could add a constructor and bind this to legendFormatter:

constructor() {
  super();
  this.legendFormatter = this.legendFormatter.bind(this);
}

Or you could make your legendFormatter function into a property initialized arrow function instead:

legendFormatter = (data) => {
  // ...
};
Tholle
  • 108,070
  • 19
  • 198
  • 189
  • Hi. The problem it's not accessing 'this' from legendFormatter. It's accessing 'this' and variables from the onclick callback. – Pedro Saraiva Jan 23 '17 at 10:55
0

To access this you need to bind the legendFormatter function

You can make use of arrow function for that

legendFormatter = (data) => {

Also to access f() and x you can try the JSX approach like

legendFormatter = (data) => {
    if (data.x == null) {
        // This happens when there's no selection and {legend: 'always'} is set.

        let f = () => {
            data.dygraph.setVisibility(0, false);
            data.dygraph.updateOptions({})
        }

        return <br>{data.series.map( (series) => {
                      return {series.dashHTML}<label onClick={f()}>{series.labelHTML}</label><br>
                      }, this);
                }

        let x = data.dygraph;

        return <br>{ data.series[0].dashHTML}<label onClick={()=>console.log(x);}>{data.series[0].labelHTML}</label>
 } 
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Hi. The problem it's not accessing 'this' from legendFormatter. It's accessing 'this' and variables from the onclick callback. If I return a JSX object in the legendFormatter function it gets rendered as "[object Object]" probably because dygraphs rendering code. – Pedro Saraiva Jan 23 '17 at 10:54