2

I'm writing an application which pulls data from a server into a wrapper component, formats the data, and passes it to multiple chart components. However, when I go to create the chart object, I get the error: TypeError: item is null.

Here's my code:

dashboard.component.html

<h1>A</h1>
<app-chart *ngIf="dataLoaded | async" [type]="'charta'" [data]="{labels: this.data.labels, readings: this.data.charta}"></app-chart>
<h1>B</h1>
<app-chart *ngIf="dataLoaded | async" [type]="'chartb'" [data]="{labels: this.data.labels, readings: this.data.chartb}"></app-chart>

chart.component.html

<div style="display: block;">
<canvas [attr.id]="type" width="400" height="400" >{{ chart }}</canvas>
</div>

chart.component.ts

....
export class ChartComponent implements OnInit {
  @Input() data: any;
  @Input() type: string;

  chart: any;

  createChart() {
    const canvas = this.elementRef.nativeElement.querySelector(`#${this.type}`);
    this.chart = new Chart(canvas, {....});
  }

  ....

  ngAfterContentInit() {
    this.createChart();
  }
}

Any ideas?

2 Answers 2

2

Probably too late, but still, what worked for me in a similar issue was the order of things.

Following the example on Chart.js I have placed the charting portion in a test.js, which I called at the start of the body tag. That was followed by the canvas. The error was due to the fact that the canvas needs to appear before the js call.

For example, index.php:

<html lang="en">
    <head>
        <title>Charting</title>
    </head>

    <body>
        <script src="node_modules/chart.js/dist/Chart.js"></script>

        <canvas id="myChart" width="400" height="400"></canvas>
        <script src="test.js"></script>
    </body>
</html>

and then test.js:

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        backgroundColor: [
            'rgba(255, 99, 132, 0.2)',
            'rgba(54, 162, 235, 0.2)',
            'rgba(255, 206, 86, 0.2)',
            'rgba(75, 192, 192, 0.2)',
            'rgba(153, 102, 255, 0.2)',
            'rgba(255, 159, 64, 0.2)'
        ],
        borderColor: [
            'rgba(255,99,132,1)',
            'rgba(54, 162, 235, 1)',
            'rgba(255, 206, 86, 1)',
            'rgba(75, 192, 192, 1)',
            'rgba(153, 102, 255, 1)',
            'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});
Sign up to request clarification or add additional context in comments.

1 Comment

wow..you are right..the order of things, I was using vuejs and I had to initialize on mounted instead of created..thanks
1

You could try using ViewChild instead

Try this

chart.component.html

<div style="display: block;">
<canvas #myChart width="400" height="400" ></canvas>
</div>

chart.component.ts

export class ChartComponent implements OnInit {
  @Input() data: any;
  @Input() type: string;

  chart: any;

  @ViewChild('myChart')
  myChart: ElementRef;

  createChart() {
    const canvas = this.myChart.nativeElement.getContext("2d");
    this.chart = new Chart(canvas, {....});
  }

  ....

  ngAfterContentInit() {
    this.createChart();
  }
}

1 Comment

I ended up fixing it by passing this.type as a string to new Chart() and then calling the function in ngAfterViewInit()

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.