Chart.js:9352 Error in generating chart. Dynamic chart creation unsuccessful

I encountered an issue while attempting to dynamically generate charts in my Angular project.

Error: Chart.js failed to create chart due to inability to acquire context from the given item.

export class StudentStudyProgressComponent implements OnInit {
  charts = [];
  semesters = [1, 2, 3, 4, 5, 6];

  constructor(private logic: LogicService) {
  }

  ngOnInit() {
    this.createCharts(this.semesters);
  }

  private createCharts(semesters: number[]) {
  semesters.forEach((semester)=>{

   this.charts.push(
    new Chart('chartStudyProgress' + semester, {
      type: 'doughnut',
      data: {
        labels: ['Passed', 'Taken', 'Remaining'],
        datasets: [
          {
            data: this.logic.getProgressForSemester(this.student.Curriculum, semester),
            borderColor: "#3cba9f",
            backgroundColor: [
              ('#66B266'),
              ('#FFFF66'),
              ('#FF7F7F')
            ]
          }
        ]
      },
      options: {
        title: {
          display: true,
          text: 'Semester '+semester
        },
        legend: {
          display: false
        },
      }
    })
   );
  });
 }
}

The error seems to be related to dynamically creating the charts in the HTML:

 <div class="row" *ngFor="let semester of semesters">
  <div class="col-4">
   <div [hidden]="!charts">
    <canvas id="{{'chartStudyProgress'+semester}}" style="max-width: 30%;">{{ charts[semester] }}</canvas>
   </div>
  </div>
 </div>

If I define the charts statically, it works fine:

<div class="row" >
 <div class="col-4">
  <div [hidden]="!charts">
   <canvas id="chartStudyProgress1" style="max-width: 30%;">{{ charts[1] }}</canvas>
   <canvas id="chartStudyProgress2" style="max-width: 30%;">{{ charts[2] }}</canvas>
   <canvas id="chartStudyProgress3" style="max-width: 30%;">{{ charts[3] }}</canvas>
   <canvas id="chartStudyProgress4" style="max-width: 30%;">{{ charts[4] }}</canvas>
   <canvas id="chartStudyProgress5" style="max-width: 30%;">{{ charts[5] }}</canvas>
   <canvas id="chartStudyProgress6" style="max-width: 30%;">{{ charts[6] }}</canvas>
  </div>
 </div>
</div>

Seeking expert assistance to resolve the dynamic chart creation issue.

Answer №1

To ensure you are accessing canvases only after they have been created in the view, it is recommended to use ngAfterViewInit instead of ngOnInit:

ngAfterViewInit() {
  this.generateCharts(this.semesters);
}

Answer №2

Although I'm no expert, it seems to me that the setup for declaring charts might need a slight adjustment. In my opinion, it would be more appropriate to structure it in the following manner:

<canvas
        id="{{'chartStudyProgress'+semester}}"
        [data]="chartData"
        [labels]="chartLabels"
        [chartType]="chartType"
        [legend]="chartLegend"
        [colors]="chartColors"
        [options]="chartOptions">
</canvas>

Subsequently, the variables should be declared in the corresponding TypeScript file. Here is an example of how this can be achieved:

this.chartData = this.logic.fetchStudyProgressForSemester(this.student.Curriculum, semester); 
this.chartType = 'doughnut';
this.chartColors = [
            {
                backgroundColor: [('#66B266'), ('#FFFF66'), ('#FF7F7F')],
                borderColor: "#3cba9f"
            }
        ];
this.chartOptions = {
    title: {
      display: true,
      text: 'Semester '+semester
    },
    legend: {
      display: false
    }
}

If you find this information helpful, please let me know. Best of luck with your project!

Answer №3

My determination with Angular 12:

const element = document.getElementById(id);
if (!element) return;

and in HTML:

<canvas id="{{id}}"></canvas>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Resetting values in Angular Reactive Forms

I have a complex FormGroup that includes multiple FormControls, FormGroups, and FormArrays. In order to reset the form to its initial state, I need to save the initial values, which may be fetched from the server as JSON data. The challenge is to reset th ...

Is there a way to identify legitimate contacts and phone numbers within an Android application using Javascript or Typescript?

I am developing an Android app where I need to show a list of contacts and specify if they are part of the app's network. However, my goal is to only display valid contacts while excluding unwanted ones such as toll-free numbers or data balance check ...

What is the best way to organize inputs in a column? I have included a reference below to show my desired layout

<mat-form-field appearance="standard"> <mat-label>Full Name *</mat-label> <input matInput [(ngModel)]="currentUser.fullName"> </mat-form-field> <mat-form-field appearance="standard"&g ...

What is the best way to insert information into my SQLite database?

Hey there! I'm new to programming and recently started working on an IONIC App. However, I've hit a roadblock. My goal is to create a phone book feature where users can get random JSON contacts and save them to their sqlite database. Here's ...

Tips for updating routerlink in navigation bar in Angular 4

I'm encountering an issue with routing to the wrong routelink. How can I prevent this from happening? My apologies for my lack of experience. The error message displayed in the Chrome console is: ERROR Error: Uncaught (in promise): Error: Cannot mat ...

Display the Slug in the Website URL upon clicking on a Blog Post using Angular and Strapi framework

When a user clicks on a blog, I want the URL to display the slug instead of the ID. My frontend framework is Angular and I have created a service to fetch data from the backend built with Strapi. Currently, when selecting a blog from the view, the URL disp ...

Deployment of a NextJS14 app to Vercel encountered an issue: Unexpected token '<' found in JSON at position 0

Here is the issue at hand: next: 14.1.4 next-auth: 4.24.7 node version: 20 This is the structure of my authentication folder: No errors occur when running npm run dev I've been investigating this issue for three days, but I am still stuck. I belie ...

Error: Query is not valid

I'm encountering an error when trying to run this query, and I'm not sure why it's returning a bad request. My goal is to fetch a specific user from the database using the accountId. Can someone assist me with this issue? Below is the funct ...

Deploying a Typescript-enabled Express application on the Azure cloud platform

Currently, I am attempting to deploy an Express server on Typescript on Azure by following the guidelines provided in this tutorial: https://learn.microsoft.com/en-us/azure/app-service/quickstart-nodejs?tabs=windows&pivots=development-environment-vsco ...

The version of the replication configuration schema does not support the use of ReplicationTime

I am currently working on setting up S3 Replication using the AWS CDK. I have referenced https://github.com/rogerchi/cdk-s3-bucketreplication/blob/main/src/index.ts as a starting point, and while it does create a replication rule, I am facing some issues c ...

Updating an Angular component: identifying the whole component as needing refresh

Is there a simpler method to set the dirty property at the component level without using ng-model and ids? I know that these can be used to access properties like dirty and pristine as stated in the Angular documentation. I have a component that contains ...

Angular CRUD Form Data Conversion Update

After selecting the date 3/2/2021 in my Angular create CRUD form, it gets passed to MongoDB as 2021-03-02T00:00:00.000+00:00 and then displayed on the update CRUD form as 2021-03-02T00:00:00.000Z. How can I convert this to 'M/d/yyyy' format? (I ...

Global variables in Ionic 2 and Angular 2 are essential for storing data that needs

Recently delving into the realm of Ionic2/Angular 2, I find myself in a state of confusion. Imagine I have a variable within a class structured as follows: export class HomePage { array: string[]; } Here's my query - how can I access the data ...

Struggle with implementing enums correctly in ngSwitch

Within my application, I have implemented three buttons that each display a different list. To control which list is presented using Angular's ngSwitch, I decided to incorporate enums. However, I encountered an error in the process. The TypeScript co ...

The Angular Swimlane Ngx chart is experiencing functionality issues when used locally, despite working perfectly on stackblitz

My experience with Angular is at a very beginner level, but I have tried to educate myself by reading some documentation and watching videos. When running the sample application of angular through this link, it works fine online. However, when I downloade ...

Encountering an issue with resolving parameters for the DecimalPipe in ngBootstrap/Angular2

Just delving into the world of Angular2 and trying to learn through hands-on experience. However, I've hit a roadblock! I attempted to import ng-bootstrap and encountered this error: https://i.stack.imgur.com/QDVJ3.png Here's my systemjs.config ...

developing a collection of Material UI text fields

My goal is to construct an accordion containing several textfield mui-components. I have developed a unique render function incorporating all the essential tags and syntax for creating a text field component. Now, I am looking to generate an array of text ...

Assigning values based on conditions for unions of types

I'm currently exploring typescript and facing a challenge with dynamically assigning values to a union type: type Labs = (name === 'dakota') ? 'fruit' | 'veg' : 'plow' | 'field' | 'till'; An ...

Accessing the placeholder attribute value of an ngcontrol in a TypeScript .ts file

I have encountered an issue where the placeholder attribute is showing as undefined in a TypeScript .ts file. Here is the code snippet I wrote: HTML Code- <label class="lab1">Closing date</label> <input placeholder="M/d/yyyy" type="text" [ ...

What are the two different ways to declare a property?

I am trying to update my interface as shown below interface Student{ Name: String; age: Number; } However, instead of the current structure, I would like it to be like this interface Student{ Name: String; age | DOB: Number | Date; } This means t ...