I am building a dashboard using Angular for a side project for myself. I have a csv file that I upload and read in the UI. I have created a parsers and everything works: the charts are generated with the correct data, random colors and everything. Since all my data shares the same value for the date and time, I want to synchronise the charts so when I hover over data entry ex. 8999 on one chart, it's going to show the data at 8999 on all charts. Something like this if: https://canvasjs.com/javascript-charts/synchronized-charts/
onFileSelected(event: any): void {
const file: File = event.target.files[0];
if (file) {
this.parseCSV(file);
}
}
parseCSV(file: File): void {
const reader = new FileReader();
reader.onload = (e: any) => {
try {
const csvData = e.target.result;
const csvRows = csvData.split('\n');
const timestampDps = [];
const chartDps: any[] = [];
const chartNames = csvRows[0].split(',').slice(1); // Get names from the first row, excluding timestamp
for (let i = 1; i < csvRows.length; i++) {
const columns = csvRows[i].split(',');
// Skip empty or incomplete rows
if (columns.length !== 6) { // Max number of sensors (N-1)
continue;
}
const timestamp = parseInt(columns[0]);
const dataEntry = parseFloat(columns[1]);
timestampDps.push({ x: timestamp, y: dataEntry });
// Extract data for each chart (modify as needed based on your columns)
const chartValues = columns.slice(1).map(parseFloat);
chartDps.push({
x: timestamp,
...chartValues.reduce((acc: { [x: string]: any; }, value: any, index: number) => {
acc[`y${index + 1}`] = value;
return acc;
}, {})
});
}
// Update common timestamp data
this.chartData = [...timestampDps];
// Ensure chartOptions and its nested properties are defined
if (!this.chartOptions.data) {
this.chartOptions.data = [];
}
// Update chart data directly, and trigger change detection
this.chartOptions.data = chartNames.map((name: any, index: number) => {
const randomColor = this.getRandomColor();
return {
type: 'line',
showInLegend: true,
legendText: name,
color: randomColor,
dataPoints: chartDps.map((d) => ({ x: d.x, y: d[`y${index + 1}`], color: randomColor }))
};
});
this.cdr.detectChanges();
} catch (error) {
console.error('Error parsing CSV file:', error);
}
};
reader.readAsText(file);
}
getRandomColor(): string {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
getChartInstance = (chart: CanvasJS.Chart) => {
this.charts.push(chart);
};
mergeOptions(baseOptions: any, additionalOptions: any): any {
return Object.assign({}, baseOptions, additionalOptions);
}
This is the parser and chart generation code that I have. As you can see it already uses canvasJS charts, but I am not sure on how to sync these charts.
This is the HTML code if anyone is intrested:
<div>
<input type="file" (change)="onFileSelected($event)" accept=".csv" />
</div>
<div *ngIf="chartData.length > 0">
<div *ngFor="let series of chartOptions.data">
<canvasjs-chart [options]="mergeOptions(chartOptions, { data: [series] })" [styles]="{ width: '100%', height:'360px' }" >
</canvasjs-chart>
</div>
</div>
I already tried to implement the sync as shown in the link, but it did not work.