pythonhighchartsnicegui

How do I put in a click event on each bar in a ui.chart (nicegui)?


My website has multiple charts and I'm trying to link them together so when the user clicks on a bar in one chart, all other charts on the website update to show only data related to that bar.

Not sure whether the click event is working, the javascript function is not being passed to the browser or whether the javascript function is invalid.

This is my code: I have tried all the methods that are commented out.

from nicegui import ui


async def handleBarClick(event):
    await ui.run_javascript(
        "alert('hello')"
    )

chart = ui.chart({
            'chart': {'type': 'bar',
                      'backgroundColor': 'rgba(0,0,0,0)',
                      },
            # 'events':{
            #             'click': "function (){alert('Hola');}"
            #         },
            
            'title': {
                'text': 'Breakdown of Fund Flow',
                'margin': 20,
                'align': 'left',
                'style': {
                    'color': '#CED5DF',
                    'fontWeight': 'bold',
                    'fontFamily': 'Michroma',
                }
            },
            
            'xAxis': {
                'type': 'category',
                'categories': ['L-L', 'L-O', 'O-L', 'O-O'],
                'labels':{
                    'style': {'color': '#CED5DF'},
                },
                    },

            
            'yAxis':{
                'title': {
                    'text': 'Amount of Funds',
                    'style': {
                        'color': '#CED5DF'
                    },
                },
                'labels':{
                            'style': {'color': '#CED5DF'}
                        },
                'gridLineDashStyle': 'dash',
            },


            'series': [{
                'name': 'Funds',
                'data': results,
                'dataLabels':{
                    'enabled': True,
                    'style': {'color': '#CED5DF'},
                    'format': '${point.y:,.2f}',
                },
                'borderWidth':0,
                'dataGrouping': False,
               # 'events': {
                #     'click': handleBarClick, 
                # },
                    }],

            'tooltip':{
                'useHTML': True,
                'headerFormat': '<table><tr><th>{point.key}</th></tr>',
                'pointFormat': '<tr><td>Amount of Funds: {point.y}</td></tr>' +
                    '<tr><td>Number of Cases: {point.count}</td></tr>',
                'footerFormat': '</table>',
                'valueDecimals': 2,
                'valuePrefix': '$',
            },

            'plotOptions':{
                'series':{
                    'bar': {
                        'color': '#db3eb1',
                        'shadow': {

                        }
                    }
                    
                    # 'point':{
                    # 'events':{
                    #     'click':"function(){alert('hello');}"
                    # },
                    # },
                },
            },

            'legend':{
                'enabled': False,
            },
            'credits': {
                'enabled': False,
            },
        }).classes('w-full h-64')

Expected output: When I click on a bar (e.g. L-L) in this chart, browser alerts "hello"


Solution

  • Unfortunately there is currently no official support for sending JavaScript callbacks to the client. But since you can run arbitrary JavaScript code (once the client is connected) you can use something like the following workaround:

    @ui.page('/')
    async def page(client: Client):
        chart = ui.chart({
            'xAxis': {
                'categories': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
            },
            'plotOptions': {
                'series': {
                    'cursor': 'pointer',
                }
            },
            'series': [{
                'data': [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
            }]
        })
        await client.connected()
        await ui.run_javascript('''
            const chart = getElement(''' + str(chart.id) + ''').chart;
            chart.update({
                plotOptions: {
                    series: {
                        point: {
                            events: {
                                click: function() {
                                   alert('Category: ' + this.category + ', value: ' + this.y);
                                }
                            }
                        }
                    }
                }
            });
            ''', respond=False)
    

    See https://github.com/zauberzeug/nicegui/discussions/936 for a similar discussion.