0👍
Here is a naïve approach using legendCallback
.
If you want multiple legend items, out of the box, you will need multiple datasets. Typically, each dataset gets its own label.
const ctx = document.getElementById('canvas').getContext('2d');
const data = [
{ Name: 'John' , FeesPaid: 100 , MemberType: 'NonMember' },
{ Name: 'Mary' , FeesPaid: 87 , MemberType: 'Member' },
{ Name: 'Charles' , FeesPaid: 108 , MemberType: 'Member' },
{ Name: 'Fern' , FeesPaid: 91 , MemberType: 'Member' },
{ Name: 'Robert' , FeesPaid: 100 , MemberType: 'NonMember' },
{ Name: 'Andrea' , FeesPaid: 114 , MemberType: 'Member' },
]
const fields = [
{ label: 'Member' , color: 'rgb(255, 99, 132)' , active: true },
{ label: 'NonMember' , color: '#f5be0b' , active: true }
];
const Colors = fields.reduce((obj, field) => ({ ...obj, [field.label]: field.color }), {});
const labels = data.map(item => item.Name);
const values = data.map(item => item.FeesPaid);
const getColor = record => {
const r = data.find(d => d.Name === record.chart.data.labels[record.dataIndex]);
return r ? Colors[r.MemberType] : Colors.NonMember;
};
const customLegendRenderer = (chart) => {
return `
<ul class="custom-legend ${chart.id}-legend">
${fields.map(field => `
<li data-field="${field.label}" data-active="${field.active}">
<span style="background-color:${field.color}"></span>
${field.label}
</li>
`).join('')}
</ul>
`;
};
const chart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
backgroundColor: getColor,
borderColor: getColor,
data: values
}]
},
options: {
legend: false,
legendCallback: customLegendRenderer
}
});
const handleClick = (e) => {
const labels = chart.data.labels;
const dataset = chart.data.datasets[0];
const item = e.target.closest('li');
if (item === null) return;
const selected = fields.find(field => field.label === item.dataset.field);
selected.active = !selected.active;
const activeFields = fields.filter(field => field.active).map(field => field.label);
while (dataset.data.length && labels.length) {
dataset.data.pop();
labels.pop();
}
const filteredData = data.filter(record => activeFields.includes(record.MemberType));
filteredData.forEach(item => {
dataset.data.push(item.FeesPaid);
labels.push(item.Name);
});
chart.update();
customLegend.innerHTML = chart.generateLegend();
};
const customLegend = document.querySelector('#chartjs-legend');
customLegend.innerHTML = chart.generateLegend();
customLegend.addEventListener('click', handleClick);
.custom-legend {
display: flex;
flex-direction: row;
justify-content: space-evenly;
list-style-type: none;
}
.custom-legend li[data-active="false"] {
color: #777;
text-decoration: line-through;
}
.custom-legend li span {
display: inline-block;
width: 1em;
height: 1em;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas"></canvas>
<div id="chartjs-legend" class="noselect"></div>
Source:stackexchange.com