Chart.js doesn't work after changing from CDN to NPM Package

Hi,

I want to change how to load Charts.js in my vaadin from using CDN to NPMPackage so that I can develop myproject offline.

In short my script can find Chart which is imported and i dont know how to import it. Because normal import like

import Chart from 'chart.js'
window.Chart = Chart

It doesn’t work in my script. Sorry for long explanation below. Thank in advance for who is willing to help me with patience.

my before changes:

@JavaScript("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js")
@JavaScript("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js")
@JsModule("./themes/spidercharts/spiderchart.js")
public class SpiderChartView extends VerticalLayout {

and I change to

@NpmPackage(value = "jquery", version = "3.1.1")
@NpmPackage(value = "chart.js", version = "4.4.2")
@JavaScript("../node_modules/chart.js/dist/chart.js")
@JavaScript("../node_modules/jquery/dist/jquery.js")
@JsModule("./themes/spidercharts/spiderchart.js")
public class SpiderChartView extends VerticalLayout {

and this is my spiderchart.js

function createNewLegendAndAttach(chartInstance, legendOpts) {
    var legend = new Chart.NewLegend({
        ctx: chartInstance.chart.ctx,
        options: legendOpts,
        chart: chartInstance
    });

    if (chartInstance.legend) {
        Chart.layoutService.removeBox(chartInstance, chartInstance.legend);
        delete chartInstance.newLegend;
    }

    chartInstance.newLegend = legend;
    Chart.layoutService.addBox(chartInstance, legend);
}

window.initSpiderChart = function (dataJson) {
    console.log("initSpiderChart")

    const canvasWrapper = document.getElementById('canvas-wrapper');
    const canvas = document.getElementById('spider-chart-canvas');

    canvas.width = canvasWrapper.clientWidth;
    canvas.height = canvasWrapper.clientHeight;

    var data = JSON.parse(dataJson);
    console.log("data is parsed " + data); // For debugging purposes

    // Check if data is an array
    if (!Array.isArray(data)) {
        console.error('Data is not an array:', data);
        return;
    }

    var labels = data.map(item => item.label);
    var values = data.map(item => item.value);


    Chart.NewLegend = Chart.Legend.extend({
        afterFit: function () {
            this.height = this.height +10 ;
        },
    });

    console.log("CONFIRMED::Chart.NewLegend" + Chart.NewLegend)

    Chart.plugins.register({
        beforeInit: function (chartInstance) {
            var legendOpts = chartInstance.options.legend;

            if (legendOpts) {
                createNewLegendAndAttach(chartInstance, legendOpts);
            }
        }, beforeUpdate: function (chartInstance) {
            var legendOpts = chartInstance.options.legend;

            if (legendOpts) {
                legendOpts = Chart.helpers.configMerge(Chart.defaults.global.legend, legendOpts);

                if (chartInstance.newLegend) {
                    chartInstance.newLegend.options = legendOpts;
                } else {
                    createNewLegendAndAttach(chartInstance, legendOpts);
                }
            } else {
                Chart.layoutService.removeBox(chartInstance, chartInstance.newLegend);
                delete chartInstance.newLegend;
            }
        }, afterEvent: function (chartInstance, e) {
            var legend = chartInstance.newLegend;
            if (legend) {
                legend.handleEvent(e);
            }
        }
    });

    console.log('ChartsPluginsRegistered::' + Chart.plugins)

    window.chartColors = {
        red: 'rgb(255, 99, 132)',
        orange: 'rgb(255, 159, 64)',
        yellow: 'rgb(255, 205, 86)',
        green: 'rgb(75, 192, 192)',
        blue: 'rgb(54, 162, 235)',
        purple: 'rgb(153, 102, 255)',
        grey: 'rgb(231,233,237)'
    };

    console.log('windows.charcolors::registered' + window.chartColors)

    var config = {
        type: 'radar',
        data: {
            labels: labels,
            datasets: [{
                label: labels,
                data: values,
                backgroundColor: 'rgba(255, 99, 132, 0.2)',
                borderColor: 'rgba(255, 99, 132, 1)',
                borderWidth: 1
            }]
        },
        options: {
            responsive: true,
            legend: {
                display: true,
                labels: {
                    padding: 10
                },
            },
            tooltips: {
                enabled: false,
            },
            scale: {
                ticks: {
                    beginAtZero: true,
                    max: 5,
                    stepSize: 1
                }
            }
        }
    };
    var ctx = document.getElementById("spider-chart-canvas").getContext("2d");
    window.myPie = new Chart(ctx, config);
};

And I got this error in html page using debug mode:

FlowClient-urjGN_YE.js:1 Uncaught ReferenceError: Chart is not defined

Based on this how to [Integrate JQuery into Vaadin Flow | Vaadin](https://add jquery into vaadin)

i try to improvised in my spiderchart.js

import Chart from 'chart.js'
window.Chart = Chart

window.initSpiderChart = function (dataJson) {
    console.log("initSpiderChart")

it returns another error XD

[ERROR] RollupError: "default" is not exported by "node_modules/chart.js/dist/chart.js", imported by "frontend/themes/spidercharts/spiderchart.js".

I am giving up. HELP .

best regards
sLawalata

Hi,

Made a few fixes such as:

  1. Use JsModule annotattion, here the snapshot:
@NpmPackage(value = "jquery", version = "3.1.1")
@NpmPackage(value = "chart.js", version = "4.4.2")
@JsModule("chart.js")
@JsModule("jquery")
@JavaScript("./themes/spidercharts/spiderchart.js")
public class SpiderChartView extends VerticalLayout {
}
  1. add import in my spiderchart.js like this:
import Chart from 'chart.js/auto'

window.Chart = Chart

function createNewLegendAndAttach(chartInstance, legendOpts) {
    var legend = new Chart.NewLegend({
        ctx: chartInstance.chart.ctx,
        options: legendOpts,
        chart: chartInstance
    });
...
}
Uncaught TypeError: Cannot read properties of undefined (reading 'extend')
    at window.initSpiderChart (chunk-2c8743ed7f837554b611647d05b1dde71a61248efb354895e6a22d5ad9b403fe-8B_6vIsO.js:837:694)

I still get an error. But based on my experience, it is caused by wrong version of chart :frowning:

But I still trying to find it out why.

Still open for suggestion and help :) Problem is still the same, i want to change from CDN to import Chart.js to NPM package so that i am not depend on internet when developing my apps.

many thanks

Do you have a repository to reproduce it?

I would use vaadin.frontend.hotdeploy=true in your Spring project (if it’s a Spring boot project)
That should give you a better error (the correct line) and you won’t need to start/stop the server to see the error.

The tutorial was done for webpack and not updated to vite so that might be tricky to apply it.

I don’t think that chart.js is using jquery so you can probably remove it.

With CDN you are using the version 2.5.0 of Chart and with NPM you are using the version 4.4.2.
I would try the version 4.4.2 with the CDN, fix the breaking changes.

Once it’s fixed use your spiderchart.js and add import Chart from 'chart.js/auto' on top.

There is also an addon for chartjs library: ChartJs add-on for Vaadin 14+ - Vaadin Add-on Directory I don’t know if that can help (unfortunately it’s using an old version of the library)