3

I am trying to create multiple chart in angular but I am not sure the way I try to implement will is correct or not and I am unable to create multiple charts it replacing one with another

 <div *ngIf="chartData.length !== 0">
      <app-limus-utilisation-chart
      *ngFor="let entity of chartData" [chartdata]="entity"
      ></app-limus-utilisation-chart>
    </div>

ChartComponent.ts

getStackedChart() {
        const canvas: any = document.getElementById('canvas1');
        const ctx = canvas.getContext('2d');
        
        var data = {
          labels: this.chartdata.buyernames,
         
          datasets: [{
            label: 'Utilised Limit',
            data: this.chartdata.utilisedlimitData,
            backgroundColor: '#22aa99'
          }, {
            label: 'Available Limit',
            data: this.chartdata.availablelimit,
            backgroundColor: '#994499'
          }]
        }
    
        chartJsLoaded$.pipe(take(1)).subscribe(() => {
          setTimeout(() => {
            this.myChart = new Chart(ctx, {
              type: 'bar',
              data: data,
              options: {
                tooltips: {
                  mode: 'index',
                  intersect: true,
                  position: 'custom',
                  yAlign: 'bottom'
                },
                scales: {
                  xAxes: [{
                    stacked: true
                  }],
                  yAxes: [{
                    stacked: false,
                    display: false
                  }]
                }
              }
            });
          })
    
        })
      }

I tried two ways

using view child the chart not created, getElementById chart created but the second chart replacing the first one. but I want two stacked charts side by side how to achieve this

and the current chart taking below 100 values but as per my actual requirment I need to show tootip amount like (1000000, 700000) that too currency format

Like this I tried to acheive https://stackblitz.com/edit/angular-chart-js-j26qhm?file=src%2Fapp%2Fapp.component.html

Please give suggestions

after getting answers I acheived few things

https://stackblitz.com/edit/angular-chart-js-tyggan

2 Answers 2

4
+50

The problem is this line here:

    const canvas: any = document.getElementById('canvas1');

You have multiple elements with that ID on the page (Because you did *ngFor), so it always attaches itself to the first element on the page.

Instead of using getElementByID, you should use Angular's built-in @ViewChild.

Like this:

chart.component.html:

<canvas #stackchartcanvas></canvas>

chart.component.ts:

@ViewChild("stackchartcanvas") myCanvas: ElementRef<HTMLCanvasElement>;
....
....
....
getStackedChart() {
    const canvas = this.myCanvas.nativeElement;
}

Stackblitz: https://stackblitz.com/edit/angular-chart-js-kny4en?file=src%2Fapp%2Fchart.component.ts

(Also, in your original code, this.chartData.push() ran EVERY time a checkbox was clicked, even if the checkbox was false, but that's a different, unrelated problem, which has also been fixed.)

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks it's working but tooltip not showing properly,, and how to modify the css , I want to decrease width of bar
1

You can use ViewChild to reference html element and use it inside you component. I have also modified few things in your code to toggle charts.

To summarize:

  1. Use ViewChild to access html element in your component
  2. Updated app component to toggle charts as opposed to just adding data
  3. Updated label to accept click event to toggle checkbox

Take a look at this stackblitz.

app.component.html

<label>
  <input type="checkbox" value=1
(change)="chooseEntity($event.target.checked, 1, entityData[0])">
  Microsoft
</label>
<label>
<input type="checkbox" (change)="chooseEntity($event.target.checked, 2, entityData[1])">
  IBM
</label>

<div *ngIf="chartData.length !== 0">
  <app-limus-utilisation-chart *ngFor="let entity of chartData" [chartdata]="entity"></app-limus-utilisation-chart>
</div>

chart.component.html

<div #chartReport>
    <canvas #canvas></canvas>
</div>

chart.component.ts

import {
  Component,
  ElementRef,
  Input,
  OnInit,
  ViewChild,
  ViewEncapsulation
} from "@angular/core";
import { Chart } from "chart.js";

import { OnChanges } from "@angular/core";
@Component({
  selector: "app-limus-utilisation-chart",
  templateUrl: "./chart.component.html",
  encapsulation: ViewEncapsulation.None
})
export class LimusUtilisationChartComponent implements OnInit, OnChanges {
  myChart: Chart;
  @Input() chartdata: any;
  @ViewChild("canvas") stackchartcanvas: ElementRef;

  constructor() {}
  ngOnChanges() {
    this.getStackedChart();
  }

  ngOnInit(): void {
    this.getStackedChart();
  }

  getStackedChart() {
    Chart.Tooltip.positioners.custom = function(elements, position) {
      //debugger;
      return {
        x: position.x,
        y:
          elements[0]._view.base - (elements[0].height() + elements[1].height())
      };
    };

    const canvas: any = this.stackchartcanvas.nativeElement;
    const ctx = canvas.getContext("2d");
    var data = {
      labels: this.chartdata.buyernames,

      datasets: [
        {
          label: "Utilised Limit",
          data: this.chartdata.utilisedlimitData,
          backgroundColor: "#22aa99"
        },
        {
          label: "Available Limit",
          data: this.chartdata.availablelimit,
          backgroundColor: "#994499"
        }
      ]
    };

    setTimeout(() => {
      this.myChart = new Chart(ctx, {
        type: "bar",
        data: data,
        options: {
          tooltips: {
            mode: "index",
            intersect: true,
            position: "custom",
            yAlign: "bottom"
          },
          scales: {
            xAxes: [
              {
                stacked: true
              }
            ],
            yAxes: [
              {
                stacked: false,
                display: false
              }
            ]
          }
        }
      });
    });
  }
}

4 Comments

Thanks it's working but tooltip not showing properly,, and how to modify the css , I want to decrease width of bar.how to customize the css
@SoumyaGangamwar tooltips are not working because of the way you are positioning it. For bar width you can configure barThickness on x axis: stackblitz.com/edit/angular-chart-js-cdcz9k As for CSS its very broad topic and I would sugest you take a look at chartjs documentation for specific styling you want.
Thank you , css now working , how to set range values As per my requirment I need to show amounts like (1000000, 70000000) that too curreny format but here chart taking below 100 range how to achies this? Is there any way to pass JSON in tooltiop apart from tooltip I need to another values as well?
I am not sure about range it should work may be you can share stavkblitz with the issue? For tooltip you will need to user custom tooltip to achieve that

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.