question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to create custom legend?

See original GitHub issue

How would one use the legendCallback method with this wrapper? The Chart.js docs show the function returning an HTML string, which is of course not the React way.

Thank you for your assistance!

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:17
  • Comments:19

github_iconTop GitHub Comments

14reactions
mattdellcommented, Jan 20, 2017

I’ve managed it by using the ref to the chart and the generateLegend function. Here’s my code if it helps anyone else…

import React, { Component } from 'react';
import { Line as LineChart, defaults } from 'react-chartjs-2';
import { Parser as HtmlToReactParser } from 'html-to-react';

const htmlToReactParser = new HtmlToReactParser();

defaults.global.animation = false;

const options = {
  legend: {
    display: false,
  },
};

class LineChartComponent extends Component {
  componentDidMount() {
    this.forceUpdate();
  }

  render() {
    return (
      <div>
        <LineChart data={this.props.data} options={options} ref="chart" />
        {this.refs.chart && htmlToReactParser.parse(this.refs.chart.chart_instance.generateLegend())}
      </div>
    );
  }
}

LineChartComponent.propTypes = {
  data: React.PropTypes.object,
};

export default LineChartComponent;
13reactions
qwelukecommented, Sep 11, 2019

Here is my approach without generateLegend method. Thanks to this, I also do not need to use React’s dangerouslySetInnerHTML so I have full control on my legend.

I’ve used this approach to achieve onClick events on legend because with dangerouslySetInnerHTML.

const SalesChart = (props: ChartProps) => {
  const inputEl: any = useRef(null);
  const [legendRendered, setLegendRendered] = useState(false);
  const [, forceUpdate] = useState();
  const classes = useStyles();

  const handleLegendClick = (datasetIndex: number) => {
    const chart = inputEl.current.chartInstance;
    chart.getDatasetMeta(datasetIndex).hidden =
      chart.getDatasetMeta(datasetIndex).hidden === null ? true : !chart.getDatasetMeta(datasetIndex).hidden;
    chart.update(); // re-draw chart to hide dataset
    forceUpdate({}); // re-draw component to update legend styles
  };

 ( ...... )

  const plugins = [
    {
      afterDatasetsDraw() {
        // hack to force re-render component in order to show legend
        if (!legendRendered) {
          setLegendRendered(true);
        }
      },
    },
  ];

    <React.Fragment>
      <div>
        <Line ref={inputEl} plugins={plugins} options={options} height={300} data={chart} />
      </div>

      {legendRendered && (
        <div
          style={{
            paddingLeft: `${inputEl.current.chartInstance.boxes[3].maxWidth}px`,
            paddingRight: `${inputEl.current.chartInstance.boxes[4].maxWidth}px`,
          }}
        >
          <ul className={classes.legendWrapper}>
            {inputEl.current.chartInstance.legend.legendItems.map((tick: ChartLegendLabelItem) => {
              const chart = inputEl.current.chartInstance;
              const isHidden = chart.getDatasetMeta(tick.datasetIndex).hidden;

              const bgColor: string =
                typeof tick.fillStyle === 'string'
                  ? tick.fillStyle // lines
                  : 'linear-gradient(to bottom, #13B080, rgba(23,172,126,0.4))'; // canvas gradient

              return (
                <li
                  className={`${classes.legendItem}`}
                  key={tick.datasetIndex}
                  onClick={() => handleLegendClick(tick.datasetIndex)}
                >
                  <div
                    className={`${isHidden ? classes.legendItemHidden : ''} ${classes.legendIcon}`}
                    style={{ background: bgColor }}
                  />
                  <Typography
                    variant="body1"
                    className={`${isHidden ? classes.legendItemHidden : ''} ${classes.legendItemText}`}
                  >
                    {tick.text}
                  </Typography>
                </li>
              );
            })}
          </ul>
        </div>
      )}
    </React.Fragment>
Read more comments on GitHub >

github_iconTop Results From Across the Web

Composing Custom Legends — Matplotlib 3.6.2 documentation
Composing custom legends piece-by-piece. Note. For more information on creating and customizing legends, see the following pages: Legend guide · Legend Demo.
Read more >
Make a Custom Legend in ArcGIS Pro - Tutorial - Esri
Make a custom legend in ArcGIS Pro · 1. Return to the map. · 2. In the Create Features pane, click any of...
Read more >
python - How to manually create a legend - Stack Overflow
Suppose we wanted to create a legend which has an entry for some data which is represented by a red color: import matplotlib.patches...
Read more >
Modify chart legend entries - Microsoft Support
Edit legend entries in the Select Data Source dialog box · Click the chart that displays the legend entries that you want to...
Read more >
Creating Customized Legends in Tableau - InterWorks
Create a legend. Show a legend. Be a legend. Tableau developers love a succinct workaround, especially when that workaround is more flexible ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found