I'm working on a dashboard for a web application. The application uses Flask, and the dashboard is built with the Chart.js framework. For some charts, such as a word cloud and a Choropleth to display an interactive map, I'm using Chart.js extensions, specifically chartjs-chart-wordcloud and chartjs-chart-geo, respectively. The plotting of these charts was working fine until, without any noticeable changes on my part, I started receiving the error: "Uncaught Error: 'wordCloud' is not a registered controller." and a similar error for the Choropleth chart. I am registering both controllers from these extensions.
I’ve tried other ways of importing, but I haven’t had any success. This is my code:
import {Chart, registerables} from 'https://esm.sh/chart.js@4.4.4';
import {WordCloudController, WordElement} from 'https://esm.sh/chartjs-chart-wordcloud@4.4.4';
import {
topojson,
ChoroplethController,
GeoFeature,
ProjectionScale,
ColorScale,
} from 'https://esm.sh/chartjs-chart-geo@4.3.4';
Chart.register(WordCloudController, WordElement, ChoroplethController, GeoFeature, ProjectionScale, ColorScale, ...registerables)
// [...]
function insert_cloud_word_chart(element, infos) {
const config = {
type: WordCloudController.id,
data: {
labels: infos['labels'],
datasets: [
{
label: 'Frequência',
data: infos['data'],
},
],
},
options: {
responsive: false,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
},
elements: {
word: {
fontFamily: 'sans-serif',
color: (ctx) => {
// Define uma cor para cada palavra com base no índice
const colors = ['#003D6A', '#22CBE4', '#2662F0', '#333333'];
return colors[ctx.index % colors.length];
},
}
}
},
}
new Chart(element, config)
}
I also used the console.log(Chart.registry.controllers)
function to check if Chart.js was correctly registering the controllers. The result showed that even though I called the function and the controllers were imported correctly, they are not being registered.
You have to make sure that you import the same version of chart.js
from esm.sh
that is imported by the extension modules,
chartjs-chart-wordcloud
and chartjs-chart-geo
.
Look into the file at https://esm.sh/chartjs-chart-wordcloud@4.4.4
and see what version of chart.js
it imports. Currently, it's
chart.js@4.4.6
(although the latest version of chart.js
in existence right now is 4.4.7).
Make sure that you import the exact same version in your project,
import {Chart, registerables} from 'https://esm.sh/chart.js@4.4.6';
The same with https://esm.sh/chartjs-chart-geo@4.3.4
- fortunately,
it's the same chart.js@4.4.6
.
Probably someone bumped the dependencies in existing extension modules of chart.js
on https://esm.sh to version 4.4.6
, leaving behind those who linked to previous versions.
As it happens, there is right now a (probably
short-lived) lack of version synchronization, since https://esm.sh/chart.js
,
https://esm.sh/chart.js@4
and https://esm.sh/chart.js@4.4
, all
link to the true last version, which is 4.4.7
, while all
last-version links to https://esm.sh/chartjs-chart-wordcloud
link to version 4.4.6
, so a possible best-practice recommendation to use
only major version links in your code won't work either. The truth is, chart.js version updates were uncommonly often lately.
When the versions of imported libraries like chart.js
match, everything
works nicely, as there is only one copy of chart.js
used (e.g., in this
case referenced internally as "/v135/chart.js@4.4.6/es2022/chart.mjs";
)
and everything works the same as when installed locally with the likes of npm
.
When the versions don't match, in the best case you get a bloated bundle with multiple (slightly different) copies for parts of the code.
In the worst case, you get errors, and we were here with the OP code.
What actually happened was that WordCloudController
was registered as
a plugin (by the call to Chart.register
) and not as a controller
as it should.
Tracking the source code for Chart.register
, (defined in
core.controller.js#L131
,
to core.registry#L25
,
then to core.registry#L127
,
and finally to core.typedRegistry.js#L17
,
plus core.registry.js#L12
)
one gets that a class sent as argument to the call to Chart.register
is
recognized as a custom controller if it derived from DatasetController
, as
a custom scale if it derived Scale
, as a custom element if it derived from
Element
and if all the above fail, it is taken to be a plugin.
Now, WordCloudController
is indeed derived from DatasetController
,
(see source code WordCloudController.ts#L35),
and as such it should have been registered as a controller, but in the original
setting WordCloudController
was derived from DatasetController
of
chart.js@4.4.6
, while TypedRegistry#isOfType
checked that it
had in its prototype chain DatasetController
of chart.js@4.4.4
,
and it didn't, so it registered it as a plugin, hence the error
'wordCloud' is not a regitered controller
('wordCloud'
is WordCloudController.id
).