Is your Vue.js chart malfunctioning?

I have been experimenting with chart.js and vue.js.

The component I created is called MessageGraph, and it is structured like this (with data extracted from the documentation):

<template>
    <canvas id="myChart" width="400" height="400"></canvas>
</template>

<script>
    import Chart from 'chart.js';

    export default {
        created() {
            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
                            }
                        }]
                    }
                }
            });
        }
    }
</script>

Upon running the code, I encountered this error message in the console:

app.c47f281….js:71222 [Vue warn]: Error in created hook: 
(found in <MessageGraph> at /Users/Janssen/Code/forumv2/resources/assets/js/components/graph/MessageGraph.vue)
warn @ app.c47f281….js:71222
handleError @ app.c47f281….js:72107
callHook @ app.c47f281….js:72939
Vue._init @ app.c47f281….js:74420
...
TypeError: Cannot read property 'length' of null
    at Object.acquireContext (app.c47f281….js:14468)
    at new Chart.Controller (app.c47f281….js:7776)
    at new Chart (app.c47f281….js:10193)
    at VueComponent.created (app.c47f281….js:2106)
    ...

To incorporate the component into my app.js file, I added the following line:

Vue.component('messageGraph', require('./components/graph/MessageGraph.vue'));

In my app.blade file, I included the following snippet:

<message-graph></message-graph>

Can you identify what might be causing this issue?

Answer №1

When working with the created() hook in Vue, keep in mind that it is called before your template is attached to the DOM, so interacting with the canvas element at this stage may cause issues.

A better approach is to move your code to the mounted() hook of your component, ensuring that the template has been mounted to the DOM. To further guarantee that the DOM is ready, consider using $vm.nextTick() (see source).

Additionally, for a more Vue-like solution, explore using vue's Child component refs instead of relying on document.getElementById().

Vue.component('message-graph', {

  template: '<canvas ref="chart" width="400" height="400"></canvas>',

  mounted() {
    this.$nextTick(() => {

      let myChart = new Chart(this.$refs.chart, {
        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
              }
            }]
          }
        }
      })

    })
  }

})

let vue = new Vue({
  el: '#app',
  template: '<div class="myApp"><message-graph></message-graph></div>'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.js"></script>

<div id="app"></div>

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

Executing a JavaScript function within Python using Selenium: A beginner's guide

Within my JavaScript, there is a function called 'checkdata(code)' which requires an argument named 'code' to execute and returns a 15-character string. I recently discovered how to call functions without arguments in JavaScript. Howev ...

Here are some steps for generating a non-integer random number that is not in the format of 1.2321312312

I am looking to create random numbers that are not integers, for example 2.45, 2.69, 4.52, with a maximum of two decimal places. Currently, the generated number includes many decimal places like 2.213123123123 but I would like it to be displayed as 2.21. ...

Highlight or unhighlight text using Javascript

Currently, I am facing a challenge in highlighting specific words on an HTML page. Although I have succeeded in highlighting the desired element, I am struggling with unhighlighting the previous word when a new search is conducted. Despite my attempts to i ...

Looking for a more efficient method to pass components with hooks? Look no further, as I have a solution ready for

I'm having trouble articulating this query without it becoming multiple issues, leading to closure. Here is my approach to passing components with hooks and rendering them based on user input. I've stored the components as objects in an array an ...

What drawbacks should be considered when utilizing meteor.js for development?

After viewing the meteor.js screencast, I was truly impressed by its seamless web application development capabilities, especially in terms of live updates and database synchronization. However, I am curious about its scalability once the website goes live ...

Guide to creating AngularJS directive attributes without a right-hand side in hiccup code?

I'm currently developing an AngularJS application using markup in hiccup format. Here is a snippet of the markup: <div modal-show modal-visible="showDialog" .........></div> Below is the corresponding Hiccup I have created: [:div.modal. ...

Using Javascript to attach <head> elements can be accomplished with the .innerHTML property, however, it does not work with XML child nodes

Exploring new ways to achieve my goal here! I want to include one JS and one jQuery attachment for each head section on every page of my static website. My files are: home.html <head> <script src="https://ajax.googleapis.com/ajax/libs/jquer ...

Looking for tips on resolving issues with the bootstrap navigation bar?

Check out this code snippet: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport ...

What is the best way to achieve this in Node.js/Express using Redis? Essentially, it involves saving a callback value to a variable

Here is the data structure I have set up in redis. I am looking to retrieve all values from the list and their corresponding information from other sets. Data structure : lpush mylist test1 lpush mylist test2 lpush mylist test3 set test1 "test1 value1" ...

Leverage global functions when implementing Vue directives

Attempting to implement lodash methods (_.isEmpty) within Vue directives as shown below: <div class="post" v-for="post in posts"></div> ... <div class="comments" v-if="! _.isEmpty(post.comments)"> <div class="comment" v- ...

Verify if the v-dialog is currently active and pause the audio playback

I am looking to implement a watcher on the v-dialog to stop audio files from playing when the dialog is open. Typically, I would use v-model="dialogVisible" and then add a watch function. However, because I have multiple dialogs, I am using v-model="media. ...

Utilizing VUE to transfer JSON data from a click event to an HTML template

I have recently started learning Vue and I am looking to pass the fetched data from a successful API call, which is in JSON format, to the HTML variable {{info}}. When I use the console.log(info), it displays the correct JSON content. Also, when utilizing ...

Tips for keeping MUI Autocomplete open even when the input field loses focus

I am currently working with a MUI autocomplete feature that includes a list of items and an edit icon next to each one. The edit icon allows the user to change the name of the option by rerendering it as a textfield. However, I have encountered an issue wh ...

Encounter the error message "Socket closure detected" upon running JSReport in the background on a RHEL system

I'm encountering an issue with JSReport at www.jsreport.net. When I run npm start --production in the background, everything seems to be working fine. But as soon as I close this session, an error pops up: Error occurred - This socket is closed. Sta ...

Next.js allows for passing dynamically loaded server-side data to all components for easy access

(I've recently started working with Next.js and inherited a project built using it, so please forgive me if this is something obvious that I'm missing) I have a set of data that needs to be loaded server-side on each request. Initially, I had im ...

Extract data from dynamically loaded tables using PhantomJS and Selenium Webdriver

I've been informed by everyone that I should be able to retrieve the table content using PhantomJS when working with JavaScript. However, despite my attempts, I have not been successful. My expectation was to obtain the table from the website Page 1 ...

Issue with jquery curvy corners not functioning properly on Internet Explorer 8

Check out my website at If you view the page in IE8 and then in IE7 compatibility mode, you'll notice a strange issue. The box on the right disappears in IE8 but displays perfectly rounded corners in IE7. I am currently using the jQuery Curvy Corner ...

The concatenation of Ajax results appears to append to the existing data

My ajax function handles uploading comments to a form, which then returns the same string. If successful, the comment is added to a comment box and the input text is cleared. The issue arises when a user adds another comment; the new comment is appended w ...

What is the process for defining an outcome when a draggable element is placed into a droppable area using Jquery?

Currently, I am working on a task where I need to increase the value of a counter (var counter = 0;) every time a draggable image is dropped into a dropzone, which is also an image rather than a div. $( "#goldbag" ).draggable({ revert: "invalid", containm ...

What is the best way to retrieve the nearest form data with jQuery after a child input has been modified?

I have a page with multiple forms, each containing several input checkboxes. When one of the form inputs changes, I want to gather all the parent form's data into a JSON array so that I can post it elsewhere. I'm having trouble putting the post ...