# DB2: Migrating chart.js from DB1

**URL:** <https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421>\
**Category:** Dashboard\
**Tags:** dashboard-2\
**Created:** [31 July 2025 16:12 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421 "2025-07-31T16:12:42Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![rakgupta](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rakgupta/32/42535_2.png) [@rakgupta](https://discourse.nodered.org/u/rakgupta)\
**Post date:** [31 July 2025 16:12 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/1 "2025-07-31T16:12:43Z")

</div>

Hi:

I am migrating 3 charts (mixed - bar/line, stacked bar) from DB1 and I can’t get the first one to work (haven’t tried others). I was looking for examples using chart.js charts with DB2, but I could not find any. Are there any changes to how things work with chart.js now?

I don’t think the new chart node will do what I need,

 ![Screenshot 2025-07-31 at 11.10.04 AM](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/1/f146b8cd27fbead8c0ab1507d1a9442486d54c34.png)

Below is a sample flow. Hoping someone can help (I am not an expert in this - took a lot of trial and error to get it working in DB1!!!)

```auto
[{"id":"907f167420b82a97","type":"inject","z":"9fe89ce15b0f9a64","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"date\":\"2025-07-01\",\"teslaFromGrid\":15.554,\"meterFromGrid\":15.714,\"teslaToGrid\":-0.099,\"meterToGrid\":-0.166},{\"date\":\"2025-07-02\",\"teslaFromGrid\":34.8,\"meterFromGrid\":35.056,\"teslaToGrid\":-0.05,\"meterToGrid\":-0.093},{\"date\":\"2025-07-03\",\"teslaFromGrid\":40.65,\"meterFromGrid\":40.92,\"teslaToGrid\":-0.037,\"meterToGrid\":-0.082},{\"date\":\"2025-07-04\",\"teslaFromGrid\":18.36,\"meterFromGrid\":18.514,\"teslaToGrid\":-0.102,\"meterToGrid\":-0.171},{\"date\":\"2025-07-05\",\"teslaFromGrid\":23.608,\"meterFromGrid\":23.769,\"teslaToGrid\":-0.077,\"meterToGrid\":-0.155},{\"date\":\"2025-07-06\",\"teslaFromGrid\":23.436,\"meterFromGrid\":23.584,\"teslaToGrid\":-0.056,\"meterToGrid\":-0.093},{\"date\":\"2025-07-07\",\"teslaFromGrid\":46.696,\"meterFromGrid\":47.009,\"teslaToGrid\":-0.081,\"meterToGrid\":-0.118},{\"date\":\"2025-07-08\",\"teslaFromGrid\":17.878,\"meterFromGrid\":18.004,\"teslaToGrid\":-0.129,\"meterToGrid\":-0.175},{\"date\":\"2025-07-09\",\"teslaFromGrid\":24.112,\"meterFromGrid\":24.5,\"teslaToGrid\":-0.063,\"meterToGrid\":-0.137},{\"date\":\"2025-07-10\",\"teslaFromGrid\":29.684,\"meterFromGrid\":29.985,\"teslaToGrid\":-0.072,\"meterToGrid\":-0.177},{\"date\":\"2025-07-11\",\"teslaFromGrid\":44.976,\"meterFromGrid\":46.001,\"teslaToGrid\":-0.064,\"meterToGrid\":-0.218},{\"date\":\"2025-07-12\",\"teslaFromGrid\":40.658,\"meterFromGrid\":41.013,\"teslaToGrid\":-0.097,\"meterToGrid\":-0.248},{\"date\":\"2025-07-13\",\"teslaFromGrid\":3.526,\"meterFromGrid\":3.635,\"teslaToGrid\":-0.09,\"meterToGrid\":-0.224},{\"date\":\"2025-07-14\",\"teslaFromGrid\":28.55,\"meterFromGrid\":28.736,\"teslaToGrid\":-0.039,\"meterToGrid\":-0.105},{\"date\":\"2025-07-15\",\"teslaFromGrid\":30.548,\"meterFromGrid\":30.869,\"teslaToGrid\":-0.11,\"meterToGrid\":-0.201},{\"date\":\"2025-07-16\",\"teslaFromGrid\":44.488,\"meterFromGrid\":44.852,\"teslaToGrid\":-0.07,\"meterToGrid\":-0.154},{\"date\":\"2025-07-17\",\"teslaFromGrid\":28.566,\"meterFromGrid\":28.843,\"teslaToGrid\":-0.045,\"meterToGrid\":-0.1},{\"date\":\"2025-07-18\",\"teslaFromGrid\":54.282,\"meterFromGrid\":54.751,\"teslaToGrid\":-0.024,\"meterToGrid\":-0.068},{\"date\":\"2025-07-19\",\"teslaFromGrid\":13.648,\"meterFromGrid\":13.73,\"teslaToGrid\":-16.551,\"meterToGrid\":-16.757},{\"date\":\"2025-07-20\",\"teslaFromGrid\":0.928,\"meterFromGrid\":0.943,\"teslaToGrid\":-9.227,\"meterToGrid\":-9.393},{\"date\":\"2025-07-21\",\"teslaFromGrid\":4.604,\"meterFromGrid\":4.668,\"teslaToGrid\":-4.552,\"meterToGrid\":-4.664},{\"date\":\"2025-07-22\",\"teslaFromGrid\":6.062,\"meterFromGrid\":6.118,\"teslaToGrid\":-10.018,\"meterToGrid\":-10.154},{\"date\":\"2025-07-23\",\"teslaFromGrid\":6.962,\"meterFromGrid\":7.03,\"teslaToGrid\":-4.244,\"meterToGrid\":-4.358},{\"date\":\"2025-07-24\",\"teslaFromGrid\":6.876,\"meterFromGrid\":6.928,\"teslaToGrid\":-9.096,\"meterToGrid\":-9.246},{\"date\":\"2025-07-25\",\"teslaFromGrid\":5.488,\"meterFromGrid\":5.534,\"teslaToGrid\":-2.726,\"meterToGrid\":-2.804},{\"date\":\"2025-07-26\",\"teslaFromGrid\":7.96,\"meterFromGrid\":8.028,\"teslaToGrid\":-0.091,\"meterToGrid\":-0.162},{\"date\":\"2025-07-27\",\"teslaFromGrid\":39.938,\"meterFromGrid\":40.279,\"teslaToGrid\":-0.063,\"meterToGrid\":-0.113},{\"date\":\"2025-07-28\",\"teslaFromGrid\":36.71,\"meterFromGrid\":37.037,\"teslaToGrid\":-0.076,\"meterToGrid\":-0.122},{\"date\":\"2025-07-29\",\"teslaFromGrid\":46.704,\"meterFromGrid\":47.157,\"teslaToGrid\":-0.074,\"meterToGrid\":-0.126}]","payloadType":"json","x":274.6470642089844,"y":799.4576807022095,"wires":[["c5ba6cece81c92c0"]]},{"id":"c5ba6cece81c92c0","type":"template","z":"9fe89ce15b0f9a64","name":"Format Energy Chart","field":"template","fieldType":"msg","format":"html","syntax":"mustache","template":"<canvas id=\"myChartTest\" width=1300 height =480></canvas>\n<script src=\"/Chart.bundle.min.js\"></script>\n<script>\nvar textcolor = getComputedStyle(document.documentElement).getPropertyValue('--nr-dashboard-widgetTextColor');\nvar gridcolor = getComputedStyle(document.documentElement).getPropertyValue('--nr-dashboard-groupBorderColor');\n//var linecolors = ['#009900','#ffa500','#aaff00','#00ffaa']\n//var linecolors = ['#009900','#3fa9e9','#EEEB51','#E68C05']\nvar linecolors = ['#5FB404','#E68C05','#0489B1','#D7DF01']\nvar barPercent = 1\n\nvar ctx = document.getElementById('myChartTest').getContext('2d');\nvar chart = new Chart(ctx, {\n // The type of chart we want to create\n type: 'bar',\n\n // The data for our dataset\n data: {\n labels: {{{payload.labels}}},\n datasets: [\n {\n type:'bar',\n label: 'Tesla - From Grid',\n backgroundColor: linecolors[0],\n stack: 'Stack0',\n borderColor: linecolors[0],\n data: {{{payload.teslaFromGrid}}},\n yAxisID: 'left-y-axis',\n steppedLine: false,\n fill: false,\n borderWidth: 3,\n pointRadius: 0\n }, \n {\n type:'bar',\n label: 'Tesla - To Grid', \n backgroundColor: linecolors[1],\n stack: 'Stack0',\n borderColor: linecolors[1],\n data: {{{payload.teslaToGrid}}},\n yAxisID: 'left-y-axis',\n barPercentage: barPercent,\n barThickness: 1,\n borderWidth: 0,\n maxBarThickness: 2,\n minBarLength: 2,\n },\n {\n type:'bar',\n label: 'Meter - From Grid', \n backgroundColor: linecolors[2],\n stack: 'Stack1',\n borderColor: linecolors[2],\n data: {{{payload.meterFromGrid}}},\n yAxisID: 'left-y-axis',\n barPercentage: barPercent,\n barThickness: 1,\n borderWidth: 0,\n maxBarThickness: 2,\n minBarLength: 2,\n }, {\n type:'bar',\n label: 'Meter - To Grid', \n backgroundColor: linecolors[3],\n stack: 'Stack1',\n borderColor: linecolors[3],\n data: {{{payload.meterToGrid}}},\n yAxisID: 'left-y-axis',\n barPercentage: barPercent,\n borderWidth: 0,\n barThickness: 1,\n maxBarThickness: 2,\n minBarLength: 2,\n }\n ]\n },\n\n // Configuration options go here\n options: {\n legend: {\n display: true,\n position:\"bottom\",\n labels: {\n fontColor: textcolor,\n fontSize: 14,\n fontStyle:\"bold\"\n }\n },\n scales: {\n yAxes: [\n {\n stacked:true,\n gridLines :{zeroLineColor:gridcolor,color:gridcolor,lineWidth:0.5},\n id: 'left-y-axis',\n type: 'linear',\n position: 'left',\n ticks: {\n fontColor:textcolor,\n fontSize: 14,\n fontStyle:\"bold\"\n },\n scaleLabel: {\n \t\t\t display: true,\n \t\t\t labelString: 'kWh',\n \t\t\t fontColor:textcolor,\n fontSize: 16,\n fontStyle:\"bold\",\n }\n }\n /*,\n {\n gridLines :{zeroLineColor:gridcolor,color:gridcolor,lineWidth:0.5},\n id: 'right-y-axis',\n type: 'linear',\n position: 'right',\n ticks: {\n fontColor:textcolor\n }\n }*/\n],\n xAxes: [\n {\n /*title: {\n text: 'Date and Time\n },*/\n stacked: true,\n gridLines :{zeroLineColor:gridcolor,color:gridcolor,lineWidth:0.5},\n ticks: {\n fontColor:textcolor,\n fontSize: 14,\n fontStyle:\"bold\",\n maxTicksLimit: 31,\n maxRotation: 90,\n minRotation:90\n },\n scaleLabel: {\n \t\t\t display: false,\n \t\t\t labelString: 'Date',\n \t\t\t fontColor:textcolor,\n fontSize: 16,\n fontStyle:\"bold\",\n }\n }\n]\n },\n plugins: {\n legend: {\n display: true,\n labels: {\n color: textcolor\n }\n },\n /*\n datalabels: {\n anchor: 'end',\n align: 'top',\n formatter: Math.round,\n font: {\n weight: 'bold'\n }\n }*/\n }\n }\n});\n</script>\n","output":"str","x":458.8345642089844,"y":799.8272094726562,"wires":[["72d8c95eee6c5357","d85a67a7156a9723"]]},{"id":"72d8c95eee6c5357","type":"debug","z":"9fe89ce15b0f9a64","name":"chart.js","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":606.8346710205078,"y":887.8271865844727,"wires":[]},{"id":"d85a67a7156a9723","type":"ui-template","z":"9fe89ce15b0f9a64","group":"","page":"","ui":"","name":"Line Chart Solar 2","order":1,"width":0,"height":0,"head":"","format":"","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":685.3051910400391,"y":801.4742212295532,"wires":[[]]}]

```

**NOTE** : I have not assigned a “group” to the template node in case it messed with anyone trying to import this flow.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [31 July 2025 18:35 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/2 "2025-07-31T18:35:23Z")

</div>

Some examples for you to investigate

> [@How to create a climograph?](https://discourse.nodered.org/t/how-to-create-a-climograph/93094):
>
> Dear all! "Climographs display data for two variables …" ([Climograph - Wikipedia](https://en.wikipedia.org/wiki/Climograph)) Basically temperature and som water-related stuff. Two axes: left: temp, right: precipitation, humidity, each w/ min/max and legend) over a period of time. How do I create such a thing w/ NR ? So far I use two separate graphs. Preferably w/ a low code approach, w/o css, template, … miracles, magic beyond my capabilities. Cheers, Uwe

---

<div class="post-metadata">

**Author:** ![rakgupta](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rakgupta/32/42535_2.png) [@rakgupta](https://discourse.nodered.org/u/rakgupta)\
**Post date:** [31 July 2025 20:14 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/3 "2025-07-31T20:14:38Z")

</div>

Thanks - I will take a deeper look. At first glance, the examples are about setting up charts using chart.js. I already have that working in DB1, so I’m not starting from scratch. It’s when I move that code to DB2 that nothing happens and I’m trying to figure out what changes may be required.

If I am not mistaken, I think you helped me get this sorted in DB1!!

---

<div class="post-metadata">

**Author:** ![rakgupta](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rakgupta/32/42535_2.png) [@rakgupta](https://discourse.nodered.org/u/rakgupta)\
**Post date:** [31 July 2025 21:02 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/4 "2025-07-31T21:02:35Z")

</div>

I looked at your sample code in the linked post and I’m not sure what changes I have to make. You mentioned that the template stuff had changed but the rest is the same. I tried to compare my working DB1 code with your DB2 sample and I’m quire confused ☹. Any help would be really appreciated - thanks

 ![Screenshot 2025-07-31 at 3.51.08 PM](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/b/7b70b5a8639dd6b7ddab6ec53972c08de999c006.jpeg)

---

<div class="post-metadata">

**Author:** ![rakgupta](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rakgupta/32/42535_2.png) [@rakgupta](https://discourse.nodered.org/u/rakgupta)\
**Post date:** [1 August 2025 13:18 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/5 "2025-08-01T13:18:12Z")

</div>

@hotNipi - I’m still trying to work through your example of the chart.js chart (Water Stuff, Temperature). It works perfectly if I copy and paste your configuration into a template node. However, your template has the data values hard coded and I will need to pass those values in.

In DB1, I was building the entire template configuration in a template node (not the chart one) and sending that into a ui\_template. I tried that by moving your entire template configuration into a template node and sending that in to ui\_template, but nothing happened.

Next I tried moving the data into an inject node (msg.labels, msg.water, msg,temperature). The data was formatted as an array but again nothing happened.

**ui-template config:**

```auto
<template>
    <div class="base-container">
        <div class="chart-container"><canvas ref="floatingbarchart" /></div>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
    export default {        
        data() {
            return {               
            }
        },
        computed: {
            
        },
        mounted() {
            this.$socket.on('msg-input:' + this.id, this.onInput)
            let interval = setInterval(() => {
                if (window.Chart) {
                    clearInterval(interval);
                    this.draw()
                }
            }, 100);
        },
        methods: {
            draw () {
                const ctx = this.$refs.floatingbarchart
                const chart = new Chart(ctx, {
                    type: 'bar',                    
                    data: {
                        labels: msg.labels,
                        datasets: [                            
                            {
                                label: 'Water stuff',
                                data:msg.water, 
                                backgroundColor: "lightblue" ,
                                yAxisID: 'y1'
                            },
                            {
                                label: 'Temperature',
                                data:msg.temperature, 
                                backgroundColor: "orange", 
                                yAxisID: 'y'
                            },                           
                        ]
                    },
                    options: {                        
                        maintainAspectRatio: false,
                        animation: false,
                        responsive: true, 
                        plugins: {
                            legend: {
                                position: 'top',
                            },
                            title: {
                                display: true,
                                text: 'Floating bar chart'
                            }
                        },
                        scales: {
                            x: {
                                stacked: false,
                            },
                            y:{
                                type: 'linear',
                                display: true,
                                position: 'right'
                            },
                            y1:{
                                type: 'linear',
                                display: true,
                                position: 'left',                                
                                grid: {
                                    drawOnChartArea: false 
                                }
                            }
                        }
                    },
                });
                this.chart = chart                
            }
        }
    }

    
</script>
<style>
    .base-container {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        container: chat / size;
    }

    .chart-container {
        position: relative;
        margin: auto;
        height: 100cqb;
        width: 100cqi;
        display: flex;
        justify-content: center;
        align-items: center;
    }
</style>

```

When reading the documentation on ui-template, it appears that I can reference msg.labels, msg.water and msg.temperature directly in the node configuration but obviously I am missing something.

The sample flow is below:

````auto
[{"id":"6726ee73c817de56","type":"inject","z":"e7206e9358b4affe","name":"","props":[{"p":"labels","v":"[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"]","vt":"json"},{"p":"water","v":"[[0,4.9],[0,3.9],[0,3.5],[0,3.4],[0,4.2],[0,7.0],[0,6.7],[0,8.1],[0,5.8],[0,7.2],[0,6.1],[0,5.3]]","vt":"json"},{"p":"temperature","v":"[[10.1,-35.0],[10.1,-27.8],[18.4,-15.8],[27.6,-6.7],[33.1,-2.5],[32.4,0.5],[35.2,0.2],[35.6,-5.2],[30.2,-17.0],[22.2,-25.9],[14.3,-34.6],[12.5,-34.6]]","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":385.6543884277344,"y":704.4613494873047,"wires":[["af5f511b315c1944","2258f21569ea4a46"]]},{"id":"2258f21569ea4a46","type":"debug","z":"e7206e9358b4affe","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":535.6580810546875,"y":764.8106079101562,"wires":[]},{"id":"af5f511b315c1944","type":"ui-template","z":"e7206e9358b4affe","group":"e0a860234b53e95c","page":"","ui":"","name":"Sample Template for Chart.js (no data)","order":2,"width":"8","height":"8","head":"","format":"<template>\n <div class=\"base-container\">\n <div class=\"chart-container\"><canvas ref=\"floatingbarchart\" /></div>\n </div>\n</template>\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n<script>\n export default { \n data() {\n return { \n }\n },\n computed: {\n \n },\n mounted() {\n this.$socket.on('msg-input:' + this.id, this.onInput)\n let interval = setInterval(() => {\n if (window.Chart) {\n clearInterval(interval);\n this.draw()\n }\n }, 100);\n },\n methods: {\n draw () {\n const ctx = this.$refs.floatingbarchart\n const chart = new Chart(ctx, {\n type: 'bar', \n data: {\n labels: msg.labels,\n datasets: [\n {\n label: 'Water stuff',\n data:msg.water, \n backgroundColor: \"lightblue\" ,\n yAxisID: 'y1'\n },\n {\n label: 'Temperature',\n data:msg.temperature, \n backgroundColor: \"orange\", \n yAxisID: 'y'\n }, \n]\n },\n options: { \n maintainAspectRatio: false,\n animation: false,\n responsive: true, \n plugins: {\n legend: {\n position: 'top',\n },\n title: {\n display: true,\n text: 'Floating bar chart'\n }\n },\n scales: {\n x: {\n stacked: false,\n },\n y:{\n type: 'linear',\n display: true,\n position: 'right'\n },\n y1:{\n type: 'linear',\n display: true,\n position: 'left', \n grid: {\n drawOnChartArea: false \n }\n }\n }\n },\n });\n this.chart = chart \n }\n }\n }\n\n\n \n</script>\n<style>\n .base-container {\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n container: chat / size;\n }\n\n .chart-container {\n position: relative;\n margin: auto;\n height: 100cqb;\n width: 100cqi;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":735.8346252441406,"y":656.8272094726562,"wires":[[]]},{"id":"e0a860234b53e95c","type":"ui-group","name":"Chart.js Sample","page":"7be6ad874ea8999b","width":"10","height":"10","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"7be6ad874ea8999b","type":"ui-page","name":"Test Chart.js","ui":"de5759a313e7ad79","path":"/page19","icon":"","layout":"grid","theme":"e4b50d7892c4eb32","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":8,"className":"","visible":"true","disabled":"false"},{"id":"de5759a313e7ad79","type":"ui-base","name":"Node-RED Dashboard","path":"/dashboard","appIcon":"","includeClientData":false,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"headerContent":"dashboard","navigationStyle":"fixed","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"e4b50d7892c4eb32","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}}]
```

````

Thanks again for your help. I’m hoping that once I understand what I’m doing wrong, I should be able to move my DB1 charts to DB2 🤞🏼

**UPDATE:** Figured out what was missing. I had to use **this.msg.labels, this.msg.water, this.msg.temperature** instead of just msg.labels etc. Now on to the next roadblock!

---

<div class="post-metadata">

**Author:** ![rakgupta](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rakgupta/32/42535_2.png) [@rakgupta](https://discourse.nodered.org/u/rakgupta)\
**Post date:** [2 August 2025 16:18 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/6 "2025-08-02T16:18:27Z")

</div>

Well - I hit the next roadblock☹️. I’ve gotten the chart formatted and working but I cannot get the chart to refresh UNTIL I physically refresh the dashboard page.

**Sample Chart:**

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/5/a5f4cbba4f140d66ba2aa3ba35aebece72c50871.png)

In the debug panel, I can see the changed dates being sent and the updated SQL statement returning the data, but the chart does not refresh.

@hotNipi - I’m seeing the same behavior in the sample template that you had referenced in your post. I modified the flow to send in the data (instead of hardcoding it) and then modified the data in a second inject node. The chart does not refresh until I manually refresh it. In looking at the chart.js documentation, there are methods to “destroy” or “clear” the chart but I can’t figure out where that needs to happen. Would really appreciate some help here. Thanks for your consideration.

**Sample flow:**

```auto
[{"id":"6726ee73c817de56","type":"inject","z":"e7206e9358b4affe","name":"Inject 1","props":[{"p":"labels","v":"[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"]","vt":"json"},{"p":"water","v":"[[0,4.9],[0,3.9],[0,3.5],[0,3.4],[0,4.2],[0,7.0],[0,6.7],[0,8.1],[0,5.8],[0,7.2],[0,6.1],[0,5.3]]","vt":"json"},{"p":"temperature","v":"[[10.1,-35.0],[10.1,-27.8],[18.4,-15.8],[27.6,-6.7],[33.1,-2.5],[32.4,0.5],[35.2,0.2],[35.6,-5.2],[30.2,-17.0],[22.2,-25.9],[14.3,-34.6],[12.5,-34.6]]","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":386.6543884277344,"y":628.4613790512085,"wires":[["af5f511b315c1944","2258f21569ea4a46"]]},{"id":"af5f511b315c1944","type":"ui-template","z":"e7206e9358b4affe","group":"e0a860234b53e95c","page":"","ui":"","name":"Sample Chart.js (injected data)","order":2,"width":"8","height":"8","head":"","format":"<template>\n <div class=\"base-container\">\n <div class=\"chart-container\"><canvas ref=\"floatingbarchart99\" /></div>\n </div>\n</template>\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n<script>\n export default { \n data() {\n return { \n }\n },\n computed: {\n \n },\n mounted() {\n this.$socket.on('msg-input:' + this.id, this.onInput)\n let interval = setInterval(() => {\n if (window.Chart) {\n clearInterval(interval);\n this.draw()\n }\n }, 100);\n },\n methods: {\n draw () {\n const ctx = this.$refs.floatingbarchart99\n const chart = new Chart(ctx, {\n type: 'bar', \n data: {\n labels: this.msg.labels,\n datasets: [\n {\n label: 'Water stuff',\n data:this.msg.water, \n backgroundColor: \"lightblue\" ,\n yAxisID: 'y1'\n },\n {\n label: 'Temperature',\n data:this.msg.temperature, \n backgroundColor: \"orange\", \n yAxisID: 'y'\n }, \n]\n },\n options: { \n maintainAspectRatio: false,\n animation: false,\n responsive: true, \n plugins: {\n legend: {\n position: 'top',\n },\n title: {\n display: true,\n text: 'Floating bar chart - inejected data'\n }\n },\n scales: {\n x: {\n stacked: false,\n },\n y:{\n type: 'linear',\n display: true,\n position: 'right'\n },\n y1:{\n type: 'linear',\n display: true,\n position: 'left', \n grid: {\n drawOnChartArea: false \n }\n }\n }\n },\n });\n this.chart = chart \n }\n }\n }\n\n\n \n</script>\n<style>\n .base-container {\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n container: chat / size;\n }\n\n .chart-container {\n position: relative;\n margin: auto;\n height: 100cqb;\n width: 100cqi;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":715.8346252441406,"y":656.8272094726562,"wires":[[]]},{"id":"2258f21569ea4a46","type":"debug","z":"e7206e9358b4affe","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":550.6581115722656,"y":569.810622215271,"wires":[]},{"id":"e3e41bab3b5530ef","type":"inject","z":"e7206e9358b4affe","name":"Inject 2","props":[{"p":"labels","v":"[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"]","vt":"json"},{"p":"water","v":"[[10,14.9],[10,13.9],[10,13.5],[10,13.4],[10,14.2],[10,17],[10,16.7],[10,18.1],[10,15.8],[10,17.2],[10,16.1],[10,15.3]]","vt":"json"},{"p":"temperature","v":"[[10.1,-35.0],[10.1,-27.8],[18.4,-15.8],[27.6,-6.7],[33.1,-2.5],[32.4,0.5],[35.2,0.2],[35.6,-5.2],[30.2,-17.0],[22.2,-25.9],[14.3,-34.6],[12.5,-34.6]]","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":400.8345642089844,"y":728.827223777771,"wires":[["af5f511b315c1944","ca7010eba0765db2"]]},{"id":"ca7010eba0765db2","type":"debug","z":"e7206e9358b4affe","name":"debug 10","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":564.8346252441406,"y":757.7095336914062,"wires":[]},{"id":"e0a860234b53e95c","type":"ui-group","name":"Chart.js Sample","page":"7be6ad874ea8999b","width":"10","height":"10","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"7be6ad874ea8999b","type":"ui-page","name":"Test Chart.js","ui":"de5759a313e7ad79","path":"/page19","icon":"","layout":"grid","theme":"682b37bffc90cac5","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":8,"className":"mytheme","visible":"true","disabled":"false"},{"id":"de5759a313e7ad79","type":"ui-base","name":"Node-RED Dashboard","path":"/dashboard","appIcon":"","includeClientData":false,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"headerContent":"dashboard","navigationStyle":"fixed","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"682b37bffc90cac5","type":"ui-theme","name":"Rakesh Dark","colors":{"surface":"#097479","primary":"#337278","bgPage":"#000000","groupBg":"#000000","groupOutline":"#337278"},"sizes":{"density":"comfortable","pagePadding":"6px","groupGap":"5px","groupBorderRadius":"1px","widgetGap":"6px"}}]

```

---

<div class="post-metadata">

**Author:** ![Buckskin](https://avatars.discourse-cdn.com/v4/letter/b/b9e5f3/32.png) [@Buckskin](https://discourse.nodered.org/u/Buckskin)\
**Post date:** [2 August 2025 20:54 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/7 "2025-08-02T20:54:08Z")

</div>

Hi, this is a bit rough and is based on the way that the input data is formatted but it seems to work

```auto
[{"id":"6726ee73c817de56","type":"inject","z":"506727cd93754bdb","name":"Inject 1","props":[{"p":"labels","v":"[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"]","vt":"json"},{"p":"water","v":"[[0,4.9],[0,3.9],[0,3.5],[0,3.4],[0,4.2],[0,7.0],[0,6.7],[0,8.1],[0,5.8],[0,7.2],[0,6.1],[0,5.3]]","vt":"json"},{"p":"temperature","v":"[[10.1,-35.0],[10.1,-27.8],[18.4,-15.8],[27.6,-6.7],[33.1,-2.5],[32.4,0.5],[35.2,0.2],[35.6,-5.2],[30.2,-17.0],[22.2,-25.9],[14.3,-34.6],[12.5,-34.6]]","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1450,"y":4640,"wires":[["af5f511b315c1944","2258f21569ea4a46"]]},{"id":"af5f511b315c1944","type":"ui-template","z":"506727cd93754bdb","group":"5b24cf2ee1a2af1c","page":"","ui":"","name":"Sample Chart.js (injected data)","order":2,"width":"8","height":"8","head":"","format":"<template>\n <div class=\"base-container\">\n <div class=\"chart-container\"><canvas ref=\"floatingbarchart99\" /></div>\n </div>\n</template>\n\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n\n<script>\n export default { \n data() {\n return {\n isChartLoaded: false,\n\n dataSets: [],\n \n }\n },\n\n computed: {\n \n },\n\n watch: {\n msg: function () {\n if (this.isChartLoaded) {\n if (this.msg.labels !== undefined) this.onInput(this.msg)\n\n }\n\n }\n\n },\n\n mounted() {\n //this.$socket.on('msg-input:' + this.id, this.onInput)\n let interval = setInterval(() => {\n if (window.Chart) {\n // The chart.js is loaded, so we can now use it\n clearInterval(interval)\n this.draw()\n \n this.isChartLoaded = true\n \n }\n\n }, 100)\n\n },\n\n methods: {\n draw () {\n const ctx = this.$refs.floatingbarchart99\n const chart = new Chart(ctx, {\n type: 'bar', \n data: {\n labels: [],\n datasets: [\n {\n label: 'Water stuff',\n data: [], //this.msg.water, \n backgroundColor: \"lightblue\" ,\n yAxisID: 'y1'\n },\n\n {\n label: 'Temperature',\n data: [], //this.msg.temperature, \n backgroundColor: \"orange\", \n yAxisID: 'y'\n }, \n ]\n },\n\n options: { \n maintainAspectRatio: false,\n animation: false,\n responsive: true, \n plugins: {\n legend: {\n position: 'top',\n },\n title: {\n display: true,\n text: 'Floating bar chart - inejected data'\n }\n },\n scales: {\n x: {\n stacked: false,\n },\n y:{\n type: 'linear',\n display: true,\n position: 'right'\n },\n y1:{\n type: 'linear',\n display: true,\n position: 'left', \n grid: {\n drawOnChartArea: false \n }\n }\n }\n },\n })\n\n this.chart = chart \n },\n\n onInput(inputData) {\n let chartData = []\n // Note with existing data format number of data points based on number of labels\n let dataLength = inputData.labels.length\n for (i = 0; i < dataLength; i++) {\n let data = {labels: inputData.labels[i],\n water: inputData.water[i],\n temperature: inputData.temperature[i]\n }\n\n chartData.push(data)\n\n } \n \n if (Array.isArray(chartData)) {\n if (chartData.length === 0) {\n this.clearChart()\n\n return\n \n } else {\n // Configure the dataSets property as the chart datasets and clear any data values\n this.dataSets = this.chart.data.datasets\n this.dataSets.forEach(element => element.data = [])\n this.chart.data.labels = []\n\n chartData.forEach(point => {\n this.chart.data.labels.push(point.labels)\n this.dataSets[0].data.push(point.water)\n this.dataSets[1].data.push(point.temperature)\n\n })\n\n this.updateChart()\n\n }\n\n }\n\n },\n\n updateChart() {\n if (this.chart) {\n this.dataSets.forEach((element, index) => {\n this.chart.data.datasets[index].data = element.data\n \n })\n \n this.chart.update()\n\n }\n\n },\n\n clearChart() {\n if (this.dataSets.length > 0) {\n this.dataSets.forEach(element => element.data = [])\n\n this.updateChart()\n\n }\n\n },\n\n }\n\n }\n\n\n \n</script>\n<style>\n .base-container {\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n container: chat / size;\n }\n\n .chart-container {\n position: relative;\n margin: auto;\n height: 100cqb;\n width: 100cqi;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n</style>","storeOutMessages":true,"passthru":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":1770,"y":4660,"wires":[["dda08729d7e95920"]],"info":"<template>\r\n <div class=\"base-container\">\r\n <div class=\"chart-container\"><canvas ref=\"floatingbarchart99\" /></div>\r\n </div>\r\n</template>\r\n\r\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\r\n\r\n<script>\r\n export default { \r\n data() {\r\n return {\r\n isChartLoaded: false,\r\n\r\n dataSets: [],\r\n \r\n }\r\n },\r\n\r\n computed: {\r\n \r\n },\r\n\r\n watch: {\r\n msg: function () {\r\n if (this.isChartLoaded) {\r\n //if (this.msg.labels !== undefined) this.onInput(this.msg)\r\n\r\n }\r\n\r\n }\r\n\r\n },\r\n\r\n mounted() {\r\n this.$socket.on('msg-input:' + this.id, this.onInput)\r\n let interval = setInterval(() => {\r\n if (window.Chart) {\r\n // The chart.js is loaded, so we can now use it\r\n clearInterval(interval)\r\n this.draw()\r\n \r\n this.isChartLoaded = true\r\n \r\n }\r\n\r\n }, 100)\r\n\r\n },\r\n\r\n methods: {\r\n draw () {\r\n const ctx = this.$refs.floatingbarchart99\r\n const chart = new Chart(ctx, {\r\n type: 'bar', \r\n data: {\r\n labels: [],\r\n datasets: [\r\n {\r\n label: 'Water stuff',\r\n data: [], //this.msg.water, \r\n backgroundColor: \"lightblue\" ,\r\n yAxisID: 'y1'\r\n },\r\n\r\n {\r\n label: 'Temperature',\r\n data: [], //this.msg.temperature, \r\n backgroundColor: \"orange\", \r\n yAxisID: 'y'\r\n }, \r\n ]\r\n },\r\n\r\n options: { \r\n maintainAspectRatio: false,\r\n animation: false,\r\n responsive: true, \r\n plugins: {\r\n legend: {\r\n position: 'top',\r\n },\r\n title: {\r\n display: true,\r\n text: 'Floating bar chart - inejected data'\r\n }\r\n },\r\n scales: {\r\n x: {\r\n stacked: false,\r\n },\r\n y:{\r\n type: 'linear',\r\n display: true,\r\n position: 'right'\r\n },\r\n y1:{\r\n type: 'linear',\r\n display: true,\r\n position: 'left', \r\n grid: {\r\n drawOnChartArea: false \r\n }\r\n }\r\n }\r\n },\r\n })\r\n\r\n this.chart = chart \r\n },\r\n\r\n onInput(inputData) {\r\n let chartData = []\r\n let len = inputData.labels.length\r\n for (i = 0; i < len; i++) {\r\n let data = {}\r\n data.labels = inputData.labels[i]\r\n data.water = inputData.water[i]\r\n data.temperature = inputData.temperature[i]\r\n\r\n chartData.push(data)\r\n\r\n } \r\n \r\n if (Array.isArray(chartData)) {\r\n if (chartData.length === 0) {\r\n this.clearChart()\r\n\r\n return\r\n \r\n } else {\r\n this.send(chartData[2])\r\n this.chart.data.labels = []\r\n this.dataSets[0] = {data: []}\r\n this.dataSets[1] = {data: []}\r\n chartData.forEach(point => {\r\n this.chart.data.labels.push(point.labels)\r\n this.dataSets[0].data.push(point.water)\r\n this.dataSets[1].data.push(point.temperature)\r\n\r\n })\r\n\r\n this.send({labels: this.chart.data.labels})\r\n\r\n this.updateChart()\r\n\r\n }\r\n\r\n }\r\n\r\n },\r\n\r\n updateChart() {\r\n if (this.chart) {\r\n this.chart.data.datasets[0].data = this.dataSets[0].data\r\n this.chart.data.datasets[1].data = this.dataSets[1].data\r\n\r\n this.chart.update()\r\n\r\n }\r\n\r\n },\r\n\r\n clearChart() {\r\n if (this.dataSets.length > 0) {\r\n this.dataSets.forEach(element => element.data = [])\r\n\r\n this.updateChart()\r\n\r\n }\r\n\r\n },\r\n\r\n }\r\n\r\n }\r\n\r\n\r\n \r\n</script>\r\n<style>\r\n .base-container {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n container: chat / size;\r\n }\r\n\r\n .chart-container {\r\n position: relative;\r\n margin: auto;\r\n height: 100cqb;\r\n width: 100cqi;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n }\r\n</style>\r\n"},{"id":"2258f21569ea4a46","type":"debug","z":"506727cd93754bdb","name":"debug 8","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1614.0037231445312,"y":4581.3492431640625,"wires":[]},{"id":"e3e41bab3b5530ef","type":"inject","z":"506727cd93754bdb","name":"Inject 2","props":[{"p":"labels","v":"[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"]","vt":"json"},{"p":"water","v":"[[10,14.9],[10,13.9],[10,13.5],[10,13.4],[10,14.2],[10,17],[10,16.7],[10,18.1],[10,15.8],[10,17.2],[10,16.1],[10,15.3]]","vt":"json"},{"p":"temperature","v":"[[10.1,-35.0],[10.1,-27.8],[18.4,-15.8],[27.6,-6.7],[33.1,-2.5],[32.4,0.5],[35.2,0.2],[35.6,-5.2],[30.2,-17.0],[22.2,-25.9],[14.3,-34.6],[12.5,-34.6]]","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1464.18017578125,"y":4740.3658447265625,"wires":[["af5f511b315c1944","ca7010eba0765db2"]]},{"id":"ca7010eba0765db2","type":"debug","z":"506727cd93754bdb","name":"debug 10","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1628.1802368164062,"y":4769.248154640198,"wires":[]},{"id":"dda08729d7e95920","type":"debug","z":"506727cd93754bdb","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2120,"y":4660,"wires":[]},{"id":"5b24cf2ee1a2af1c","type":"ui-group","name":"Power","page":"c8690e5bce80ab2a","width":6,"height":1,"order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"c8690e5bce80ab2a","type":"ui-page","name":"Analysis","ui":"b810194ea14e3502","path":"/analysis","icon":"database-eye","layout":"flex","theme":"5075a7d8e4947586","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"24"}],"order":6,"className":"","visible":"true","disabled":"false"},{"id":"b810194ea14e3502","type":"ui-base","name":"Dashboard 2 Examples","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-control","ui-notification"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"5075a7d8e4947586","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"6px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}},{"id":"42ba1fa2135222ec","type":"global-config","env":[],"modules":{"@flowfuse/node-red-dashboard":"1.26.0"}}]

```

---

<div class="post-metadata">

**Author:** ![rakgupta](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rakgupta/32/42535_2.png) [@rakgupta](https://discourse.nodered.org/u/rakgupta)\
**Post date:** [2 August 2025 22:34 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/8 "2025-08-02T22:34:20Z")

</div>

> [@Buckskin](#):
>
> it seems to work

It does! I’m also trying to understand what would cause this, so if you could explain the changes, I would really appreciate it.

As far as I can see, the changes were in the “export” section:

Your code:

```auto
<script>
    export default {        
        data() {
            return {
                isChartLoaded: false,

                dataSets: [],
                            
            }
        },

        computed: {
            
        },

        watch: {
             msg: function () {
                if (this.isChartLoaded) {
                    if (this.msg.labels !== undefined) this.onInput(this.msg)

                }

            }

        },

        mounted() {
            //this.$socket.on('msg-input:' + this.id, this.onInput)
            let interval = setInterval(() => {
                if (window.Chart) {
                    // The chart.js is loaded, so we can now use it
                    clearInterval(interval)
                    this.draw()
    
                    this.isChartLoaded = true
    
                }

            }, 100)

        },

```

Original Code:

```auto
export default {        
        data() {
            return {               
            }
        },
        computed: {
            
        },
        mounted() {
            this.$socket.on('msg-input:' + this.id, this.onInput)
            let interval = setInterval(() => {
                if (window.Chart) {
                    clearInterval(interval);
                    this.draw()
                }
            }, 100)
            //this.draw()
        },

```

Was clearing out the dataset (dataSets) what was needed? Thanks again for your help. Hopefully I can make this change in the chart that I’m trying to change as well.

**Update:**

Oh - I see a lot of changes! I guess the original ui-template that I had used as a starting point was really for static data and there really was no logic to update/refresh the chart. I see that in your version. Thanks so much - that helps a lot. 🙏🏼

---

<div class="post-metadata">

**Author:** ![rakgupta](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rakgupta/32/42535_2.png) [@rakgupta](https://discourse.nodered.org/u/rakgupta)\
**Post date:** [4 August 2025 15:04 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/9 "2025-08-04T15:04:19Z")

</div>

@Buckskin - I got it working!! And ChatGPT (after 2 days) was finally able to simplify the code a bit.

Below is the flow in case it helps someone:

```auto
[{"id":"f8c7169724fa4baf","type":"inject","z":"3d460c91742c0584","name":"Updated Meter Data (w/payload1)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"labels\":[\"2025-07-15\",\"2025-07-16\",\"2025-07-17\",\"2025-07-18\",\"2025-07-19\",\"2025-07-20\",\"2025-07-21\",\"2025-07-22\",\"2025-07-23\",\"2025-07-24\",\"2025-07-25\",\"2025-07-26\",\"2025-07-27\",\"2025-07-28\",\"2025-07-29\",\"2025-07-30\",\"2025-07-31\",\"2025-08-01\"],\"teslaFromGrid\":[30.548,44.488,28.566,54.282,13.648,0.928,4.604,6.062,6.962,6.876,5.488,7.96,39.938,36.71,46.704,50.692,53.876,45.47],\"meterFromGrid\":[30.869,44.852,28.843,54.751,13.73,0.943,4.668,6.118,7.03,6.928,5.534,8.028,40.279,37.037,47.157,51.154,54.372,45.84],\"teslaToGrid\":[-0.11,-0.07,-0.045,-0.024,-16.551,-9.227,-4.552,-10.018,-4.244,-9.096,-2.726,-0.091,-0.063,-0.076,-0.074,-0.066,-0.057,-0.065],\"meterToGrid\":[-0.201,-0.154,-0.1,-0.068,-16.757,-9.393,-4.664,-10.154,-4.358,-9.246,-2.804,-0.162,-0.113,-0.122,-0.126,-0.083,-0.074,-0.07]}","payloadType":"json","x":384.8345642089844,"y":320.82720947265625,"wires":[["8e254e2bad333e5c"]]},{"id":"8e254e2bad333e5c","type":"ui-template","z":"3d460c91742c0584","group":"5cd7a2a79d14beb5","page":"","ui":"","name":"Clean Temlate for Testing","order":1,"width":"22","height":"10","head":"","format":"<template>\n <div class=\"base-container\">\n <div class=\"chart-container\"><canvas ref=\"meterchart0\" /></div>\n </div>\n</template>\n\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n\n<script>\n export default { \n data() {\n return {\n isChartLoaded: false,\n dataSets: [],\n }\n },\n\n watch: {\n msg: function () {\n if (this.isChartLoaded && this.msg.payload && this.msg.payload.labels) {\n this.onInput(this.msg.payload);\n }\n }\n },\n\n mounted() {\n let interval = setInterval(() => {\n if (window.Chart) {\n clearInterval(interval);\n this.draw();\n this.isChartLoaded = true;\n }\n }, 100);\n },\n\n methods: {\n draw() {\n const ctx = this.$refs.meterchart0;\n const chart = new Chart(ctx, {\n type: 'bar',\n data: {\n labels: [],\n datasets: [\n {\n label: 'Tesla - From Grid',\n data: [],\n backgroundColor: \"lightblue\",\n stack: 'tesla'\n },\n {\n label: 'Meter - From Grid',\n data: [],\n backgroundColor: \"red\",\n stack: 'meter'\n },\n {\n label: 'Tesla - To Grid',\n data: [],\n backgroundColor: \"orange\",\n stack: 'tesla'\n },\n {\n label: 'Meter - To Grid',\n data: [],\n backgroundColor: \"green\",\n stack: 'meter'\n }\n ]\n },\n options: {\n maintainAspectRatio: false,\n animation: false,\n responsive: true,\n plugins: {\n legend: {\n position: 'top',\n },\n title: {\n display: true,\n text: 'Tesla vs Meter - Injected data'\n }\n },\n scales: {\n x: {\n stacked: true,\n },\n y: {\n type: 'linear',\n display: true,\n position: 'left'\n }\n }\n },\n });\n\n this.chart = chart;\n },\n\n onInput(inputData) {\n if (!inputData || !Array.isArray(inputData.labels)) return;\n\n this.dataSets = this.chart.data.datasets;\n\n // Clear previous data\n this.dataSets.forEach(dataset => dataset.data = []);\n this.chart.data.labels = [];\n\n // Assign new data directly from arrays\n this.chart.data.labels = inputData.labels;\n this.dataSets[0].data = inputData.teslaFromGrid;\n this.dataSets[1].data = inputData.meterFromGrid;\n this.dataSets[2].data = inputData.teslaToGrid;\n this.dataSets[3].data = inputData.meterToGrid;\n\n this.updateChart();\n },\n\n updateChart() {\n if (this.chart) {\n this.dataSets.forEach((element, index) => {\n this.chart.data.datasets[index].data = element.data;\n });\n this.chart.update();\n }\n },\n\n clearChart() {\n if (this.dataSets.length > 0) {\n this.dataSets.forEach(element => element.data = []);\n this.updateChart();\n }\n }\n }\n }\n</script>\n\n<style>\n .base-container {\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n container: chat / size;\n }\n\n .chart-container {\n position: relative;\n margin: auto;\n height: 100cqb;\n width: 100cqi;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":670.6471252441406,"y":395.3216857910156,"wires":[["ea6162aff0119e33"]]},{"id":"8dc54484cd9c7e23","type":"inject","z":"3d460c91742c0584","name":"Updated Meter Data (w/payload2)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"labels\":[\"2025-07-15\",\"2025-07-16\",\"2025-07-17\",\"2025-07-18\",\"2025-07-19\",\"2025-07-20\",\"2025-07-21\",\"2025-07-22\",\"2025-07-23\",\"2025-07-24\",\"2025-07-25\",\"2025-07-26\",\"2025-07-27\",\"2025-07-28\",\"2025-07-29\",\"2025-07-30\",\"2025-07-31\",\"2025-08-01\"],\"teslaFromGrid\":[60.548,104.488,88.566,114.282,73.648,63.928,64.604,66.062,66.962,66.876,65.488,67.96,99.938,96.71,106.704,110.692,113.876,105.47],\"meterFromGrid\":[30.869,44.852,28.843,54.751,13.73,0.943,4.668,6.118,7.03,6.928,5.534,8.028,40.279,37.037,47.157,51.154,54.372,45.84],\"teslaToGrid\":[-0.11,-0.07,-0.045,-0.024,-16.551,-9.227,-4.552,-10.018,-4.244,-9.096,-2.726,-0.091,-0.063,-0.076,-0.074,-0.066,-0.057,-0.065],\"meterToGrid\":[-0.201,-0.154,-0.1,-0.068,-16.757,-9.393,-4.664,-10.154,-4.358,-9.246,-2.804,-0.162,-0.113,-0.122,-0.126,-0.083,-0.074,-0.07]}","payloadType":"json","x":379.8345642089844,"y":470.82720947265625,"wires":[["8e254e2bad333e5c"]]},{"id":"ea6162aff0119e33","type":"debug","z":"3d460c91742c0584","name":"Output debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":911.6471252441406,"y":396.8106384277344,"wires":[]},{"id":"5cd7a2a79d14beb5","type":"ui-group","name":"Tesla vs Meter - Testing","page":"8d56444ee1e5169e","width":"22","height":"10","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"8d56444ee1e5169e","type":"ui-page","name":"New Page for Testing","ui":"de5759a313e7ad79","path":"/page21","icon":"home","layout":"grid","theme":"e4b50d7892c4eb32","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":22,"className":"","visible":"true","disabled":"false"},{"id":"de5759a313e7ad79","type":"ui-base","name":"Node-RED Dashboard","path":"/dashboard","appIcon":"","includeClientData":false,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"headerContent":"dashboard","navigationStyle":"fixed","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"e4b50d7892c4eb32","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}}]

```

Below is the code for ui-template:

> **ui-template configuration:**
>
> ```auto
> <template>
> <div class="base-container">
> <div class="chart-container"><canvas ref="meterchart0" /></div>
> </div>
> </template>
> 
> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
> 
> <script>
> export default {        
> data() {
> return {
> isChartLoaded: false,
> dataSets: [],
> }
> },
> 
> watch: {
> msg: function () {
> if (this.isChartLoaded && this.msg.payload && this.msg.payload.labels) {
> this.onInput(this.msg.payload);
> }
> }
> },
> 
> mounted() {
> let interval = setInterval(() => {
> if (window.Chart) {
> clearInterval(interval);
> this.draw();
> this.isChartLoaded = true;
> }
> }, 100);
> },
> 
> methods: {
> draw() {
> const ctx = this.$refs.meterchart0;
> const chart = new Chart(ctx, {
> type: 'bar',
> data: {
> labels: [],
> datasets: [
> {
> label: 'Tesla - From Grid',
> data: [],
> backgroundColor: "lightblue",
> stack: 'tesla'
> },
> {
> label: 'Meter - From Grid',
> data: [],
> backgroundColor: "red",
> stack: 'meter'
> },
> {
> label: 'Tesla - To Grid',
> data: [],
> backgroundColor: "orange",
> stack: 'tesla'
> },
> {
> label: 'Meter - To Grid',
> data: [],
> backgroundColor: "green",
> stack: 'meter'
> }
> ]
> },
> options: {
> maintainAspectRatio: false,
> animation: false,
> responsive: true,
> plugins: {
> legend: {
> position: 'top',
> },
> title: {
> display: true,
> text: 'Tesla vs Meter - Injected data'
> }
> },
> scales: {
> x: {
> stacked: true,
> },
> y: {
> type: 'linear',
> display: true,
> position: 'left'
> }
> }
> },
> });
> 
> this.chart = chart;
> },
> 
> onInput(inputData) {
> if (!inputData || !Array.isArray(inputData.labels)) return;
> 
> this.dataSets = this.chart.data.datasets;
> 
> // Clear previous data
> this.dataSets.forEach(dataset => dataset.data = []);
> this.chart.data.labels = [];
> 
> // Assign new data directly from arrays
> this.chart.data.labels = inputData.labels;
> this.dataSets[0].data = inputData.teslaFromGrid;
> this.dataSets[1].data = inputData.meterFromGrid;
> this.dataSets[2].data = inputData.teslaToGrid;
> this.dataSets[3].data = inputData.meterToGrid;
> 
> this.updateChart();
> },
> 
> updateChart() {
> if (this.chart) {
> this.dataSets.forEach((element, index) => {
> this.chart.data.datasets[index].data = element.data;
> });
> this.chart.update();
> }
> },
> 
> clearChart() {
> if (this.dataSets.length > 0) {
> this.dataSets.forEach(element => element.data = []);
> this.updateChart();
> }
> }
> }
> }
> </script>
> 
> <style>
> .base-container {
> width: 100%;
> height: 100%;
> display: flex;
> justify-content: center;
> align-items: center;
> container: chat / size;
> }
> 
> .chart-container {
> position: relative;
> margin: auto;
> height: 100cqb;
> width: 100cqi;
> display: flex;
> justify-content: center;
> align-items: center;
> }
> </style>
> 
> ```

You can do almost the same in the chart node in DB2 but stacking is not an option and also, I have other charts that are a mix of line/bar charts, hence the dive into chart.js

I hope this helps someone. Again - thank you @Buckskin and @hotNipi . Could not have done this without your help 🙏🏼

> **Sample Output**
>
> ![Screenshot 2025-08-04 at 10.00.33 AM](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/3/03912e3adacdcc38894b34262aa8a6c1f5bc620a.png)

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [18 August 2025 15:04 UTC](https://discourse.nodered.org/t/db2-migrating-chart-js-from-db1/98421/10 "2025-08-18T15:04:52Z")

</div>

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