Reputation: 2554
I'm using react-chartjs-2 to create a Line chart for my application.
For this app, I did a legend customisation and I could generate them using this:
// Chart component
<Line ref={ (chart) => chart ? this.insertLegends(chart) : null }
data={this.state.chart}
options={this.state.options}
/>
// Method which insert the html content
insertLegends(chart) {
this.refs.chartLegendContainerGlobal.innerHTML = chart.chart_instance.generateLegend();
}
First, is this a right approach? I had to create an inline condition inside the component to prevent chart to be null.
Second, how and where can I put an onClick event for each legend?
I'm very lost on this, is there a better way to do this legend customisation??
Upvotes: 0
Views: 6334
Reputation: 2554
After some trouble and research, I figure out how to add the legend and control the click inside of it.
// Inside my render method I added a simple ref to my component
<Line ref='chart' data={this.convertData(this.props.data)} options={this.state.options} />
// Inside this method I'm able to get all the references that
// I need to inject the html inside a container for the legends and
// also to assign a click for each legend label
componentDidMount() {
let legends = this.refs.chart.chart_instance.generateLegend();
this.refs.chartLegendContainer.innerHTML = legends;
$(this.refs.chartLegendContainer).find('.legend-item').on('click', (e) => {
let index = $(e.currentTarget).index();
this.refs.chart.chart_instance.data.datasets[index].hidden = !this.refs.chart.chart_instance.data.datasets[index].hidden;
$(e.currentTarget).toggleClass('disable-legend');
this.refs.chart.chart_instance.update();
});
}
UPDATED
After the commect of @Chase DeAnda, I changed a little bit based on his considerations:
// Applying the callback function to the ref
<Line ref={this.applyRef} data={this.convertData(this.props.data)} options={this.state.options} />
// Inside the method I call the method to insert the legends
applyRef(ref) {
this.legend = ref;
this.insertLegends();
}
// Generates the legend and added them to my container element
// Also give them the onClick event
insertLegends() {
let legends = this.legend.chart_instance.generateLegend();
this.refs.chartLegendContainer.innerHTML = legends;
$(this.refs.chartLegendContainer).find('.legend-item').on('click', (e) => this.onClickLegend(e));
}
// During onClick I update the chart
onClickLegend(e) {
let index = $(e.currentTarget).index();
this.legend.chart_instance.data.datasets[index].hidden = !this.legend.chart_instance.data.datasets[index].hidden;
$(e.currentTarget).toggleClass('disable-legend');
this.legend.chart_instance.update();
}
Upvotes: 0
Reputation: 16441
If you give the ref a callback, then you won't get a value of null. Doing an inline ref like this causes the first render to be null and then the second render will have the element.
So you should change your refs to:
applyRef(ref) {
this.legend = ref;
}
render() {
return (
// Chart component
<Line ref={this.applyRef}
data={this.state.chart}
options={this.state.options}
/>
)
}
For adding a click event handler, if you can't add an onClick
attrib for some reason, then you can set it in your insertLegends
method:
handleClick(e) {
// Do something here...
}
insertLegends(chart) {
this.refs.chartLegendContainerGlobal.innerHTML = chart.chart_instance.generateLegend();
this.refs.chartLegendContainerGlobal.addEventListener('click', this.handleClick);
}
Upvotes: 1