1

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"

clj55
  • 13
  • 3
  • Hi @clj55, I am not a Python expert, but the notation: `"function(){alert('hello');}"` is probably treated as a basic string in JS. Please check this simple example: http://jsfiddle.net/BlackLabel/x782tfjd/ of how the transformed function should look like. Also, I've found the `on` method in the nicegui docs: https://nicegui.io/documentation/chart#chart which maybe resolve your issue? – ppotaczek May 19 '23 at 11:18
  • @ppotaczek Im not sure how to check how the function was transformed... The `on` method, I managed to put it on the whole chart but dont know how to put the event on individual bars – clj55 May 20 '23 at 12:05

1 Answers1

1

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.

Falko
  • 17,076
  • 13
  • 60
  • 105
  • The click event works thanks! How do I update all the charts to only show data related to the bar? E.g. If I click on 'L-L' all other charts filter the data where 'L-L' is true. I tried using `$ajax` to POST the bar's category to a an environment file .env located in the same folder as my main file so that when I rerun the page, the main file runs a modified SQL query and reloads the chart with the new data. However, I got 404 NOT FOUND error. After using `app.add_static_files` to add the .env file I got 405 METHOD NOT ALLOWED instead. – clj55 May 21 '23 at 12:48