x Axis Ticks are missing in NVD3 Line chart

Viewed 32

enter image description here

I have a nvd3 line chart where the x axis ticks don't match or align with the data points. When i hover on Jul 2021 data point, the tooltip for sep 2021 is shown. Also some of the ticks are not shown at all. The line this.tickLength = this.ChartInputData[0].values.length; value is set to the ticks.

line chart html

<div class="row">
  <div class="col-12">
    <div style="margin-left: 4em; display: inline-flex; align-items: center;">
      <label class="toyota-red bold-font margin-B0" for="">Y-Axis Format:</label>
      <mat-button-toggle-group class="margin-L15" [(ngModel)]="forceZeroTo" (change)="expandCollapse($event)"
        #group="matButtonToggleGroup">
        <mat-button-toggle *ngIf="minMaxValue === 100" matRipple [matRippleColor]="'#c0000047'"
          [matRippleUnbounded]="false" [value]="100"> 100% </mat-button-toggle>
        <mat-button-toggle *ngIf="minMaxValue === 150" matRipple [matRippleColor]="'#c0000047'"
          [matRippleUnbounded]="false" [value]="150"> 150% </mat-button-toggle>
        <mat-button-toggle matRipple [matRippleColor]="'#c0000047'" [matRippleUnbounded]="false" [value]="0">Min-Max
          Scale
        </mat-button-toggle>
      </mat-button-toggle-group>
    </div>
  </div>
  <div class="col-12">
    <nvd3 *ngIf="showMultiLineChart" #nvd3Chart [options]="multiLineChartOptions" [data]="chartData"></nvd3>
  </div>
</div>

Line Chart component

import { DatePipe } from '@angular/common';
declare const $: any;
export interface ChartLabels {
  labels: string;
}

@Component({
  selector: 'app-line-chart',
  templateUrl: './line-chart.component.html',
  styleUrls: ['./line-chart.component.scss']
})

export class LineChartComponent implements OnInit, OnChanges {
  @ViewChild('nvd3') nvd3Chart;
  @Input('chartId') chartId: number;
  @Input('dimensionLabel') dimensionLabel: string;
  @Input('chartKey') chartKey: string;
  @Input('xAxis') xAxis: string;
  @Input('yAxis') yAxis: string;
  @Input('width') width: string;
  @Input('ChartInputData') ChartInputData: any;
  @Input('resizeChart') resizeChart: string;
  @Input('minMaxValue') minMaxValue: number;
  @Input('showPercentage') showPercentage: boolean;
  @Input('showDollar') showDollar: boolean;

  public multiLineChartOptions;
  public chartData: any;
  public data;
  public chartLabelsList: any;
  public tickLength: number;
  public showMultiLineChart = false;
  customHeight: number;
  forceZeroTo: number;
  constructor() { }

  formatDate(e) {
    const datePipe = new DatePipe('en-US');
    return datePipe.transform(e, 'MM-dd-yyyy');
  }
  public getLabels() {
    this.chartLabelsList = [];
    let chartLabels: ChartLabels;
    for (let i = 0; i < this.chartData[0].values.length; i++) {
      chartLabels = {
        labels: this.chartData[0].values[i].label
      };
      this.chartLabelsList.push(chartLabels.labels);
    }
    return this.chartLabelsList;
  }
  /* to split the axis label and show ellipse*/
  ellipseLabel(data) {
    if (data) {
      length = data.length;
      if (length > 10) {
        return data.substring(0, 7) + '...';
      } else {
        return data;
      }
    }
  }

  expandCollapse(event) {
    this.forceZeroTo = event.value;
    this.generateChart(this.showPercentage, this.showDollar);
  }

  ngOnChanges(changes) {
    this.chartData = this.ChartInputData;
    this.generateChart(this.showPercentage, this.showDollar);

    setTimeout(() => {
      const resizeEvent = window.document.createEvent('UIEvents');
      resizeEvent.initEvent('resize', true, false);
      window.dispatchEvent(resizeEvent);
    }, 100);
  }
  ngOnInit() {
    this.forceZeroTo = this.minMaxValue;
    this.generateChart(this.showPercentage, this.showDollar);
    this.chartData = this.ChartInputData;
    this.delayTimer();
  }
  delayTimer() {
    setTimeout(() => {
      this.showMultiLineChart = true;
    }, 100);
  }
  generateChart(showPercentage: boolean, showDollar: boolean) {
    this.getLabels();
    this.tickLength = this.ChartInputData[0].values.length;
    this.multiLineChartOptions = {
      chart: {
        type: 'lineChart',
        height: 350,
        margin: {
          top: 20,
          right: 20,
          bottom: 75,
          left: 85
        },
        x: function (d) {
          return d.index;
        },
        y: function (d) {
          return Number(d.value);
        },
        showLegend: this.checkLegend(this.ChartInputData),
        forceY: this.checkMinMaxValue(),
        useInteractiveGuideline: false,
        dispatch: {
          stateChange: function (e) {
            console.log('stateChange');
          },
          changeState: function (e) {
            console.log('changeState');
          },
          tooltipShow: function (e) {
            console.log('tooltipShow');
          },
          tooltipHide: function (e) {
            console.log('tooltipHide');
          }
        },
        xAxis: {
          showMaxMin: false,
          rotateLabels: -45,
          tickFormat: (d, i = 0) => {
            if (i <= this.ChartInputData[0].values.length) {
              return this.chartLabelsList[i];
            }
          },
          tickValues: this.tickLength
        },
        yAxis: {
          tickFormat: function (d) {
            if (showPercentage) {
              return d3.format(',')(d.toFixed(2)) + ' %';
            } else if (showDollar) {
              return '$' + d3.format(',')(d);
            } else {
              return d3.format(',')(d);
            }
          },
          axisLabelDistance: -10
        },
        tooltip: {
          contentGenerator: function (e) {
            let value;
            if (showPercentage) {
              value = e.point.value + ' %';
            } else if (showDollar) {
              value = e.point.value + ' $';
            } else {
              value = d3.format(',')(e.point.value);
            }
            return (
              '<table><tr><td class="legend-color-guide"><div style="background-color:' +
              e.point.color +
              '"></div></td><td class="key">' +
              e.series[0].key +
              '</td><td class="key">' +
              e.point.label +
              '</td><td class="value">' +
              value +
              '</td></tr></table>'
            );
          }
        },
        callback: function (chart) { }
      }
    };
  }

  checkMinMaxValue() {
    if (this.forceZeroTo === 100) {
      return [0, 100]
    } if (this.forceZeroTo === 150) {
      return [0, 150]
    } else {
      return []
    }
  }

  checkLegend(data: any) {
    if (data && data.length === 1) {
      return false;
    } else {
      return true;
    }
  }

}

methods tried

1.setting false to showMaxMin -> didnt work

I tried to set true instead of false to showMaxMin and set the rotateLabels: -70 the first data point Aug 2021 is repeated at the end.

enter image description here

2. using tickvalues instead of ticks --> didnt work

only first and last tick values are shown and first tick is repeated at the end

enter image description here

0 Answers
Related