You need to expose chart to window. By default you cannot use any npm module outside "mix"
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
window.Chart = Chart; //this allows you to use chart outside of "mix"
Hello everybody,
I am starting with chartjs. Already tried to do something through CDN and it worked perfectly. Then, I decided to include it in project through NPM (following https://www.chartjs.org/docs/latest/getting-started/integration.html) and the graphs are not visible and get the following error:
Uncaught ReferenceError: Chart is not defined
To install it, I did the following:
npm install chartjs
Installation went OK. My dependancies look like this in package.json:
"dependencies": {
"alpinejs": "^3.7.1",
"chart.js": "^3.7.0"
}
Then, in resources/js/app.js, included the import statements. I show you the whole file so you can have context. (The alpine stuff was there before and it works)
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
import Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()
I then ran
npm run dev
which worked fine. On the CLI I can see (but it passes quite fast) some text with the word chartjs. This makes me think that I am doing fine. Also, went to app.js but in public directory and doing ctrl+f chartjs returns a number of results, so everything looks good.
I am calling the app.js in the <head> of a blade layout named "twapp" in the following manner:
<script src="{{ asset('js/app.js') }}" defer></script>
Finally, I want to use the charts in a view. The view contains the following (is the code from https://www.chartjs.org/docs/latest/getting-started/usage.html)
@extends('layouts.twapp')
@section('content')
<canvas id="myChart" width="400" height="400"></canvas>
<script>
const ctx = document.getElementById('myChart');
const 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: {
y: {
beginAtZero: true
}
}
}
});
</script>
@endsection
I think that I must be very close. After all, the process of installing AlpineJS (and I guess other JS stuff) is 99% the same and managed to make it work quite fast. I have a few hipothesis: -The graph wants to be created before the script is loaded (makes sense?) -I am doing something wrong in the install process (my favourite) -There is a bug somewhere: chartjs, laravel... (I don't think so...)
Thanks a lot and happy new year.
EDIT: I want to thank a lot Sinnbeck for the help. I make this edit to add an alternative solution to the one he provided. I did a lot of google research before asking the original question and could not find a summarized answer, so here you go:
There is a "conflict" (or at least it happens to me (Laravel 8, AlpineJS 3.X and Livewire 2.x)) between AlpineJS and chartJS. The reason is that AlpineJS requires to be included with "defer" attribute. If you put the code to load chartJS in the same file as Alpine JS, when loading the script file you will be applying "defer" attribute to chartJS as well. This casuses (at least to me) that Chart is not found. So ideally, what you want is to have chartJS and AlpineJS in different .js files and include them as separate lines. Then, you will need to mix them. What I did is to place, in resources\js, two files:
app.js
charts.js
The first one has the code needed to load AlpineJS, and the second one chartsJS. Then, at the head of my HTMLs (I have it in a blade layout, but this is not important for the solution) you call both scripts the following way:
<!-- Scripts -->
<script src="{{ asset('js/charts.js') }}"></script>
<script src="{{ asset('js/app.js') }}" defer></script>
Finally, you need to tell Laravel to pick the new js file (charts.js) from resources directory and move it to public directory. To do that, you have to modify the mix script. Mine looks like this now:
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/charts.js', 'public/js')
.postCss('resources/css/main.css', 'public/css', [
require('tailwindcss'),
])
Notice how there are two js lines. Now you run NPM with
npm run dev
And that's all. Hope its helpful for anybody.
@LaraNewDev that makes sense. As you are using it inside of mix. As I said, the problem is that Chart isn't exported to outside of mix (blade). This line will do it, but it needs to be run before your js in blade (blade is using window for Javascript)
window.Chart = Chart;
Please or to participate in this conversation.