How to import a chart into my template without using cdn

Hello, I'm new to node-red, I'm using the flowfuse dashboard 2.0 template and I would like to create custom charts in it, the problem is that the chart.js import is being done via cdn and I'm doing a project that needs to work offline , I installed chart.js in my node-red project, but I know how to import the library into my template. How can I import chart.js into the flowfuse template? Thanks.

<template>
    <canvas ref="chart" />
</template>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<script>
    export default {
        mounted() {
            // register a listener for incoming data
            this.$socket.on('msg-input:' + this.id, this.onInput)

            // code here when the component is first loaded
            let interval = setInterval(() => {
                if (window.Chart) {
                    // Babylon.js is loaded, so we can now use it
                    clearInterval(interval);
                    this.draw()
                }
            }, 100);
        },
        methods: {
            draw () {
                const ctx = this.$refs.chart
                const data = {
                    labels: [],
                    datasets: [{
                        label: 'Colors',
                        data: [],
                        backgroundColor: []
                    }]
                }
                
                // Render the chart
                const chart = new Chart(ctx, {
                    type: 'polarArea',
                    data: data,
                    options: {
                        responsive: true,
                        scales: {
                            r: {
                                pointLabels: {
                                    display: true,
                                    centerPointLabels: true,
                                    font: {
                                        size: 18
                                    }
                                }
                            }
                            },
                            plugins: {
                            legend: {
                                position: 'top',
                            },
                            title: {
                                display: true,
                                text: 'Chart.js Polar Area Chart With Centered Point Labels'
                            }
                        }
                    },
                });
                this.chart = chart
            },
            onInput (msg) {
                // in this example, our topics will be colors
                const color = msg.topic

                // have we seen this color before?
                const index = this.chart.data.labels.indexOf(color)
                
                if (index === -1) {
                    console.log('new color', color)
                    // add new dataset for this topic
                    this.chart.data.labels.push(color)
                    this.chart.data.datasets[0].data.push(msg.payload)
                    this.chart.data.datasets[0].backgroundColor.push(color)
                } else {
                    // we've already got data for this color, update the value
                    this.chart.data.datasets[0].data[index] = msg.payload
                }

                // ensure the chart re-renders
                this.chart.update()      
            }
        }
    }
</script>

Welcome to the community!

How did you do this? Through an npm install?

I managed to solve it, I modified the settings.json, added

httpStatic: [ { path: path.join(os.homedir(), '.node-red', 'st'), root: "/st/" }]

, I created the st folder and placed the chart.js file inside of it, then I imported it using


<script src="/st/chart.js"></script>

Thank you very much for your help.

1 Like

This is great, thank you, I'll add this to the documentation too as it's a very useful pattern to have

Though you probably should note in the docs Joe that this will not then be easily updated should the source library be updated. Would it be better to advise people to manually install the npm version to the userDir and create a link from that to the static folder?

Have an example please? My Node-RED-foo in this space is lacking.

No problem though not sure if this would work on FlowFuse, I've not had time to try as yet. But, on a "standard" install (assuming Linux here but Windows/Mac much the same):

cd ~/.node-red
npm install chart.js

Puts the chart.js library package into the node-red userDir along side installed node packages.

Now you have to find the correct library that does what you want - unfortunately, this can be different for every library. In theory, for front-end libraries, the package.json file for the library should contain a browser, main or module property that gives the location of the resource file that gets stuff done. But not all libraries provide that.

Interestingly, chart.js DOES provide that info so the important file would be found at ~/.node-red/node_modules/chart.js/dist/chart.umd.js.

So an ln BASH command could be used to create a link from that file to the static folder. Then any updates to the library can be as simple as:

cd ~/.node-red
npm update chart.js

The link should update automatically.

As you can see, even this isn't easy and the worse part is working out what file to use. Though that can be made easier by looking up the library on the jsdelivr CDN site.


Incidentally, this is one of the key reasons that UIBUILDER has a library manager feature. Not only does it keep the front-end libraries separated from Node-RED node libraries, it makes updates easier, but most importantly, the installed package's folder is made available for use as a web endpoint under the ../uibuilder/vendor/ path so that it becomes as easy to use as using a CDN package.

E.g. for chart,js, the resulting URL is ../uibuilder/vendor/chart.js/dist/chart.umd.js which is shown in the library manager and also on the detailed info page.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.