DB2: Migrating chart.js from DB1

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,

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!!!)

[{"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.

Some examples for you to investigate

1 Like

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!!

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 :frowning:. Any help would be really appreciated - thanks

@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:

<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:

[{"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 :crossed_fingers:t3:

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!

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:

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:

[{"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"}}]

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

[{"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"}}]
1 Like

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:

<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:

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. :folded_hands:t3:

@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:

[{"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:
<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 :folded_hands:t3:

Sample Output

1 Like