I’m having issues with creating filters for a chart. When I click one of the filters, it doesn’t seem to be correctly processing. Any ideas?
const ctx = document.getElementById('earningsChart');
const earningDates = ['2023-12-14', '2023-12-15', '2023-12-16', '2023-12-17', '2023-12-18', '2023-12-19', '2023-12-20', '2023-12-21', '2023-12-22', '2023-12-23', '2023-12-24', '2023-12-25', '2023-12-26', '2023-12-27', '2023-12-28'];
const earningDatesConverted = earningDates.map(earningDate => new Date(earningDate).setHours(0, 0, 0, 0));
const earningsData = [
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
[, , , , , , , , , , , , 1.0, 1.0, 1.0],
[, , , , , , , , , , , , 1.0, 1.0, 1.0],
[, , , , , , , , , , , , 1.0, 1.0, 1.0],
[, , , , , , , , , , , , 1.5, 1.5, 1.5],
[, , , , , , , , , , , , 2.0, 2.0, 2.0]];
const earningsChart = new Chart(ctx, {
type: 'line',
data: {
labels: earningDates,
datasets: [
{
label: 'Merchant 1',
data: earningsData[0],
fill: false,
borderColor: '#6FA1C1',
tension: 0.5,
spanGaps: true
}, {
label: 'Merchant 2',
data: earningsData[1],
fill: false,
borderColor: '#FFEB8C',
tension: 0.5,
spanGaps: true
}, {
label: 'Merchant 3',
data: earningsData[2],
fill: false,
borderColor: '#E3F687',
tension: 0.5,
spanGaps: true
}, {
label: 'Merchant 4',
data: earningsData[3],
fill: false,
borderColor: '#81D374',
tension: 0.5,
spanGaps: true
}, {
label: 'Merchant 5',
data: earningsData[4],
fill: false,
borderColor: '#7A6AB0',
tension: 0.5,
spanGaps: true
}, {
label: 'Merchant 6',
data: earningsData[5],
fill: false,
borderColor: '#D073A4',
tension: 0.5,
spanGaps: true
}, {
label: 'Merchant 7',
data: earningsData[6],
fill: false,
borderColor: '#FFCE8C',
tension: 0.5,
spanGaps: true
}
]
},
options: {
spanGaps: true,
scales: {
x: {
type: 'time',
time: {
unit: 'day'
}
},
y: {
beginAtZero: true
}
},
plugins: {
legend: {
display: true,
position: 'bottom'
},
tooltip: {
callbacks: {
title: function(tooltipItem, data) {
if( tooltipItem[0].parsed.x ) {
let dt = new Date(tooltipItem[0].parsed.x);
let dtMonth = dt.getMonth() + 1;
return dtMonth + "https://stackoverflow.com/" + dt.getDate() + "https://stackoverflow.com/" + dt.getFullYear();
}
return '';
},
label: function(context) {
let earn_rate = context.parsed.y;
let merchant_name = context.dataset.label;
return merchant_name + ': ' + earn_rate.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
},
titleFont: {
size: 18
},
bodyFont: {
size: 16
}
}
}
}
});
function filterDate() {
const filterDateStartObj = new Date(document.getElementById('filterDateStart').value);
filterDateStart = filterDateStartObj.setHours(0, 0, 0, 0);
const filterDateEndObj = new Date(document.getElementById('filterDateEnd').value);
filterDateEnd = filterDateEndObj.setHours(0, 0, 0, 0);
const filterDates = earningDatesConverted.filter(date => date >= filterDateStart && date <= filterDateEnd);
earningsChart.config.data.labels = filterDates;
const startArray = earningDatesConverted.indexOf(filterDates[0]);
const endArray = earningDatesConverted.indexOf(filterDates[filterDates.length - 1]);
const copyEarningsData = [...earningsData];
copyEarningsData.splice(endArray + 1, filterDates.length);
copyEarningsData.splice(0, startArray);
earningsChart.config.data.datasets[0].data = copyEarningsData;
earningsChart.update();
}
function filterDateReset() {
earningsChart.config.data.labels = earningDatesConverted;
earningsChart.config.data.datasets[0].data = earningsData;
document.getElementById('filterDateStart').value="2023-12-14";
document.getElementById('filterDateEnd').value="2023-12-28";
earningsChart.update();
}
function filterDateAll() {
filterDateReset();
}
function filterDate90() {
document.getElementById('filterDateStart').value="2023-09-29";
document.getElementById('filterDateEnd').value="2023-12-28";
filterDate();
}
function filterDate30() {
document.getElementById('filterDateStart').value="2023-11-28";
document.getElementById('filterDateEnd').value="2023-12-28";
filterDate();
}
function filterDate7() {
document.getElementById('filterDateStart').value="2023-12-21";
document.getElementById('filterDateEnd').value="2023-12-28";
filterDate();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.js" integrity="sha512-d6nObkPJgV791iTGuBoVC9Aa2iecqzJRE0Jiqvk85BhLHAPhWqkuBiQb1xz2jvuHNqHLYoN3ymPfpiB1o+Zgpw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<div>
<canvas id="earningsChart"></canvas>
</div><div class="container">
<div class="row">
<div class="col">
<label>Last</label>
<button onclick="filterDateAll()">All</button>
<button onclick="filterDate90()">90</button>
<button onclick="filterDate30()">30</button>
<button onclick="filterDate7()">7</button>
<label>Days</label>
</div>
<div class="col">
<label for="filterDateStart">Start</label>
<input class="lph input" type="date" id="filterDateStart" min="2023-12-14" max="2023-12-27" value="2023-12-14">
<label for="filterDateEnd" class="lph">End</label>
<input class="lph input" type="date" id="filterDateEnd" min="2023-12-15" max="2023-12-28" value="2023-12-28">
<button onclick="filterDate()">Filter</button>
<button onclick="filterDateReset()">Reset</button>
</div>
</div>
</div>
If you have a problem that shows only one line instead of all lines, here’s an answer.
As far as I think, there are some mistakes in filterDate function.
you just update dataset as below.
earningsChart.config.data.datasets[0].data = copyEarningsData;
but this means that you only update one dataset.
correct code is here.
earningsChart.config.data.labels = filterDates;
for (let i = 0; i < filteredDatasets.length; i++) {
earningsChart.config.data.datasets[i].data = filteredDatasets[i];
}
so filterDate function must be like this.
function filterDate() {
const filterDateStartObj = new Date(document.getElementById('filterDateStart').value);
filterDateStart = filterDateStartObj.setHours(0, 0, 0, 0);
const filterDateEndObj = new Date(document.getElementById('filterDateEnd').value);
filterDateEnd = filterDateEndObj.setHours(0, 0, 0, 0);
const filterDates = earningDatesConverted.filter(date => date >= filterDateStart && date <= filterDateEnd);
const startArray = earningDatesConverted.indexOf(filterDates[0]);
const endArray = earningDatesConverted.indexOf(filterDates[filterDates.length - 1]);
const filteredDatasets = earningsData.map(dataset => dataset.slice(startArray, endArray + 1));
// Update the labels and datasets' data in the chart configuration
earningsChart.config.data.labels = filterDates;
for (let i = 0; i < filteredDatasets.length; i++) {
earningsChart.config.data.datasets[i].data = filteredDatasets[i];
}
// Update the chart
earningsChart.update();
}
I think this answer will help you.
you mean, when you filter by dates, only one line showed instead of showing all lines?