How to synchronise charts in Angular

39 views Asked by At

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.

0

There are 0 answers