Node-Red Problem with BarChart Hover

Hi everyone!

I'm working on a project where I need to get data from a database and plot this data into a Bar Chart. This chart needs to be clickable, so the user can select some info, and this info will trigger some other query to fullfil the rest of the charts.

I got an issue with the bar chart hover, that don't display the right data. Here is an example:


All the X labels are showed when I need only to display the right label.
This are the object that I get from my database, and also the response of onclick event (the one that will trigger the other query).

The flow are attached.

Any help?
hover3.txt (2.2 KB)

Do you see any errors in browser console?

No errors in the console :confused:

I think that data for labels goes to wrong place ...
Here's one old example, quite similar, see what kind of data goes where.

[{"id":"3afc2e42.168ee2","type":"function","z":"09deee63c1b960f7","name":"make data","func":"let d = [];\nlet l = [];\nlet c = []\nconst getHue = (seed) => {\n    let h = Math.floor(seed * 361);\n    let s = 100;\n    let l = 50;\n    h /= 360;\n    s /= 100;\n    l /= 100;\n\n    let r, g, b;\n    if (s === 0) {\n        r = g = b = l;\n    } else {\n        const hue2rgb = (p, q, t) => {\n            if (t < 0) t += 1;\n            if (t > 1) t -= 1;\n            if (t < 1 / 6) return p + (q - p) * 6 * t;\n            if (t < 1 / 2) return q;\n            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n            return p;\n        };\n        const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n        const p = 2 * l - q;\n        r = hue2rgb(p, q, h + 1 / 3);\n        g = hue2rgb(p, q, h);\n        b = hue2rgb(p, q, h - 1 / 3);\n    }\n    const toHex = x => {\n        const hex = Math.round(x * 255).toString(16);\n        return hex.length === 1 ? '0' + hex : hex;\n    };\n   \n    return { value: seed, color: '#' + toHex(r) + toHex(g) + toHex(b),label: toHex(r) + toHex(g) + toHex(b)};\n};\n\nfor(var i = 0;i<24;++i){\n    const col = getHue(Math.random())\n    d.push(col.value)\n    c.push(col.color)\n    l.push(col.label)\n}\nmsg.payload = {data:d,colors:c,labels:l};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":1380,"wires":[["639096c5.76e7a8","64e85953cd987006"]]},{"id":"639096c5.76e7a8","type":"ui_template","z":"09deee63c1b960f7","group":"109b0b40.54c0b5","name":"BAR Chart","order":4,"width":"14","height":"6","format":"<canvas id=\"my_barchart\" width=600 height=250></canvas>\n<script>\n\n\n(function(scope) { \n    \n    \n    function createChart(){       \n        const ctx = document.getElementById(\"my_barchart\").getContext('2d');\n        const chart = new Chart(ctx, {\n            type: 'bar',\n            data: {\n                labels: [],\n                datasets: [{\n                    label: '',\n                    backgroundColor:[] ,\n                    data: [],\n                    borderWidth: 1\n                }]\n            },\n            options: {\n                scales: {\n                    xAxes: [{\n                        gridLines: {\n                            tickMarkLength:5,\n                            color: 'rgba(255,255,255,0.1)'\n                        },\n                        ticks:{\n                            fontColor:'rgba(255,255,255,0.5)',\n                            padding:20\n                        }\n                    }],\n                    yAxes: [{\n                        gridLines: {\n                            tickMarkLength:5,\n                            color: 'rgba(255,255,255,0.1)'\n                        },\n                        ticks:{\n                            fontColor:'rgba(255,255,255,0.5)',\n                            padding:20\n                        }\n                    }]\n                },\n                tooltips: {\n                    callbacks: {\n                        label: function(tooltipItem, data) {\n                            let label = tooltipItem.xLabel || '';                        \n                            if (label) {\n                                label += ': ';\n                            }\n                            label += Math.round(tooltipItem.yLabel * 1000) / 1000;\n                            return label;\n                        },\n                        title:function(tooltipItem, data){\n                            return 'Color value'\n                        }\n                    }\n                },\n                onClick: function (e) {\n                    const el = this.getElementAtEvent(e)[0];\n                    if (el) {\n                        const label = chart.data.labels[el._index];\n                        const value = chart.data.datasets[el._datasetIndex].data[el._index];\n                        scope.send({payload:value,topic:label,frontend:true})\n                    }\n                }\n            }\n            }\n        );\n        return chart\n    }\n\n\n    \n    function updateChart(chart,input) { \n        chart.data.labels = input.labels\n        chart.data.datasets[0].data = []\n        chart.data.datasets[0].backgroundColor = []\n        input.data.forEach((el,idx) => {\n            chart.data.datasets[0].data.push(el)\n            chart.data.datasets[0].backgroundColor.push(input.colors[idx])\n        })        \n        chart.update(200);\n    }\n    \n    const barchart = createChart()\n\n    scope.$watch('msg', function(msg) {\n        if (msg) {\n            if(msg.frontend){\n                return\n            }\n            if(!barchart){\n                console.log('no chart')\n                return\n            }\n            updateChart(barchart,msg.payload)\n        }\n    });\n\n\n})(scope);\n\n</script>","storeOutMessages":true,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":750,"y":1420,"wires":[["b045a83a99d21516","776f16809c6b0c2b"]]},{"id":"1cddf5d5.9564da","type":"inject","z":"09deee63c1b960f7","name":"Test","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":330,"y":1420,"wires":[["639096c5.76e7a8","3afc2e42.168ee2"]]},{"id":"cfe72466.cb83d8","type":"ui_button","z":"09deee63c1b960f7","name":"","group":"109b0b40.54c0b5","order":2,"width":"3","height":"1","passthru":false,"label":"random data","tooltip":"","color":"","bgcolor":"","className":"","icon":"fa-refresh","payload":"true","payloadType":"bool","topic":"","topicType":"str","x":350,"y":1380,"wires":[["3afc2e42.168ee2"]]},{"id":"ab4d4b5e.528e18","type":"ui_template","z":"09deee63c1b960f7","group":"109b0b40.54c0b5","name":"Title","order":3,"width":"14","height":"1","format":"<style>\n    #charttitle{\n        text-align:center;\n    }\n</style>\n<div id='charttitle'>COMPARE COLORS</div>\n\n","storeOutMessages":false,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":730,"y":1380,"wires":[[]]},{"id":"b045a83a99d21516","type":"debug","z":"09deee63c1b960f7","name":"chart click","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":940,"y":1420,"wires":[]},{"id":"776f16809c6b0c2b","type":"ui_text","z":"09deee63c1b960f7","group":"109b0b40.54c0b5","order":12,"width":0,"height":0,"name":"","label":"chart click","format":"{{msg.topic}}: {{msg.payload}}","layout":"row-left","className":"","x":740,"y":1480,"wires":[]},{"id":"64e85953cd987006","type":"debug","z":"09deee63c1b960f7","name":"chart data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":1340,"wires":[]},{"id":"109b0b40.54c0b5","type":"ui_group","name":"body","tab":"24b8f2c0.76ab8e","order":2,"disp":false,"width":"14","collapse":false},{"id":"24b8f2c0.76ab8e","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]
1 Like

I'll check it, thanks for the help!

Hi hotNipi!

Thanks to your code, we found an issue in our platform, related to the hover (the has only appearing when clicked), but related to the labels, we didn't found a solution. We tried to use the same approach that you show in the code, but it didn't work. I'm sending attached the flows that we are using (from the query to the plot chart). Thanks!
flows (22).json (8.5 KB)

No way I can even try it cos I don't have the database nor the data.
If you can do the test flow with dummy data, I'll try to do my best to investigate ..

We got the same issue with mocked data. All labels are showing inside tooltip. The flow is attached.
flows (24).json (5.3 KB)

<div>
    <canvas id="myChart101" style="display: flex; position: relative; top:55px"></canvas>
</div>

<script>
(function(scope) {
const ctx = document.getElementById('myChart101');
const barchart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: [],
        datasets: [
            {
                data:[],
                backgroundColor:[]
            }
        ]
    },
    options: {
        interaction: {
        mode: 'index',
        intersect: false,
        // axis: 'x'
        },
        onClick: (e) => {
            console.log(e);
            if(e.type =="click"){
                const el = barchart.getElementAtEvent(e)
                console.log(el)
                if(el && el[0] && el[0]._view){
                    const label = el[0]._view.label
                    const val = barchart.data.datasets[0].data[el[0]._index]
                    scope.send({payload:{label:label,data:val},topic:"Click_on_chart_bar"})
                }
            }
        },
        scales: {
            xAxes: [{
            barPercentage: 0.5,
                ticks: {
                    beginAtZero: true,
                    fontColor: '#f2f2f2'
                },
                gridLines :{
                    zeroLineColor:'#f2f2f2',
                    color:'#f2f2f2',
                    lineWidth:0.5
                },
            }],

            yAxes: [{
            barPercentage: 0.5,
                ticks: {
                    beginAtZero: true,
                    fontColor: '#f2f2f2'
                },
                gridLines :{
                    zeroLineColor:'#f2f2f2',
                    color:'#f2f2f2',
                    lineWidth:0.5
                },
            }],
        },
        elements: {
            rectangle: {
            borderSkipped: 'left',
            }
        },
        responsive: true,
    }
});

// update chart data
function addData(chart, data) {   
    chart.data.labels = data.label
    chart.data.datasets[0].data = []
    chart.data.datasets[0].backgroundColor = []
    data.data.forEach(el => {
        chart.data.datasets[0].data.push(el)
        chart.data.datasets[0].backgroundColor.push(data.backgroundColor)        
    })
    chart.update();
}

// watch for msg
scope.$watch('msg', (msg) => {
   if (msg) {
      // Do something when msg arrives
     addData(barchart, msg.payload)
    }
})


})(scope)

</script>

It Works!

Thanks a lot!!!!

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