plotly / dash-alternative-viz

Dash components & demos to create Altair, Matplotlib, Highcharts , and Bokeh graphs within Dash apps.
https://dash.plotly.com
MIT License
7 stars 0 forks source link

HighCharts : No callbacks triggered on User interaction. #26

Open poopiipuu opened 7 months ago

poopiipuu commented 7 months ago

The options property doesn't trigger the callback when the user interacts with HighCharts.

Is it because the HighChart.react.js only has a render( ) event and no onChange() event? This onchange() event should in some way implement a setProps in order to trigger the callcack?

Thanks for looking into this.

This issue + example code is mentioned on the plotly forum.

Example with a Gantt Chart


import dash_alternative_viz as dav
import dash_html_components as html
from dash.dependencies import Input, Output, State
import datetime, time

external_scripts = [  
    "https://code.highcharts.com/gantt/highcharts-gantt.js",
    "https://code.highcharts.com/gantt/modules/gantt.js", 
    "https://code.highcharts.com/modules/draggable-points.js"
]
app = dash.Dash(
    __name__,
    external_scripts=external_scripts
    )

def epoch_js(date_time):
    return int(time.mktime(date_time.timetuple())) * 1000

app.layout = html.Div(
    [
        html.Div("Drag the task or it's extremities to update OPTIONS PROPERTY (does not work)"),
        dav.HighChart(
            id="my_highchart",
            constructorType = 'ganttChart', 
            options = {
                'title': {
                    'text': 'Interactive Gantt Chart',
                    'align': 'left'
                    },
                'xAxis': {
                    'min': epoch_js(datetime.datetime(2023, 8, 17)),
                    'max': epoch_js(datetime.datetime(2023, 10, 30)),
                    },
                'plotOptions': {
                    'series': {
                        'animation': False, # Do not animate dependency connectors
                        'dragDrop': {
                            'draggableX': True,
                            'draggableY': True,
                            'dragMinY': 0,
                            'dragMaxY': 2,
                            'dragPrecisionX': 86400000, # 1day = 1000 * 60 * 60 * 24 (millis)
                            },
                        'dataLabels': {
                            'enabled': True,
                            'format': '{point.name}',
                            'style': {
                                'cursor': 'default',
                                'pointerEvents': 'none'
                                }
                            },
                        'allowPointSelect': True,
                        }
                    },
                'series': [
                    {
                        'name': 'Project',
                        'data': [
                            {
                                'name': 'Start prototype',
                                'start': epoch_js(datetime.datetime(2023, 9, 10)),
                                'end'  : epoch_js(datetime.datetime(2023, 10, 10)),
                                'completed': {
                                    'amount': 0.5
                                    }
                                }
                            ]
                        }
                    ],
                }
            ),
        html.Div('This should update the options property data whenever the user interacts with the Gantt Chart'),
        html.Div(id='output'),
        ]
    )

# GETTING THE OPTIONS AFTER USER INTERACTION
# DOES NOT WORK
@app.callback(  # THIS DOES NOT TIGGER AS EXPECTED !!!
    Output("output", "children"),
    Input("my_highchart", "options"),
    prevent_initial_callback = True,
    ) 
def get_options(options):
    print(options)
    return f'{options}'

if __name__ == "__main__":
   app.run_server( port = 8050, debug=False)``` 
ljilekor commented 7 months ago

A proper workaround to this issue was provided by the all mighty jinnyzor.

The alternative dives in quite deep but provides a customizable workaround.