Synchronize legend items visibility across charts

Viewed 103

How can i synchronize series visibility across charts, such that when user show/hide series in one chart, all the others chart's series visibility change as well

charts = []
renderers = []

#iterate over and gather all legend renderers
for spec in charts_specs:
    chart = createChart(spec)
    charts.append(chart)
    for legend in chart.legend:
        for legend_item in legend.items:
            renderers.append(legend_item.renderers[0])

#register for visibility changed and update matching legends in other charts
for renderer in renderers:
    renderer.js_on_change("visible", CustomJS(args=(renderer=renderer, renderers = renderers), code = """
    
    for(var index =0 ; index < renderers.length; index++)
    {
       var global_renderer = renderers[index];
       if(global_renderer.name === renderer.name)
       {
            global.renderer.visible = renderer.visible
       }
    }
    """)

#plot charts
for chart in charts:
    show(chart)

Question - with above (1) I do not see anything update (2) Why does this not cause a stack overflow with visiblity callback called recursively. I suppose i am not pushing the changes correctly?

1 Answers

I'm more of a basic Python user so I could be saying something stupid, but shouldn't you be using global_renderer.visible instead of global.renderer.visible? Maybe that's the answer to everything? I don't know actually.

Anyway, I'll tell you my approach so that you can evaluate if it's doable.

The thing is that you want all charts to switch altogether from one state to the other whenever the user asks for it, therefore, I'd use 2 global variables:

  1. A boolean to store the present state (STATE).
  2. A boolean to know if charts are in the middle of switching (CHANGING).

The behaviour of the charts would also be a bit different from yours, let me write it with pseudo-code so that it's more understandable.

1st chart would:

if not(CHANGING):
    STATE = !STATE
    CHANGING = True
    for(chart in charts):
        "visible" = STATE

Charts in the middle would:

if not(CHANGING):
    1st_chart."visible" = !STATE

Last chart would:

if not(CHANGING):
    1st_chart."visible" = !STATE
else:
    CHANGING = False

Why do it like this? This way, whenever a chart is changed by the user, it will trigger the 1st chart change, thus switching the STATE variable and activating the CHANGING mode. In this mode the 1st chart changes all of the other charts' visiblility into the new STATE. As globals are "protected" in CHANGING mode, the STATE will be the same for everybody and no recursive process should occur. Finally, when the 1st chart pulls a change into the last chart the CHANGING mode is set to False and the iteration ends.

Hope this was useful somehow ;)

Related