🚀 Gen 5 of the leading AI app deployment platform launches October 6. Click for the livestream.

Incorrect menu item displays for drop down (MRE included)

Hi,

I want to use plotly to display a different image when an item from a drop down menu is selected. I am able to get plotly to change the image on menu item selection, however the value displayed for the menu item is always incorrect.

To see this, run the example below. Select “AGPL”, the image will be updated and the menu item will be correct. Next select “Bridge” and the image will be updated but the menu item will still say “AGPL.”

I guess this has to do with using relayout? Do I need to use update instead? I also tried having a series of add_layout_image calls, changing their visibility using the update method, but this did not work for me…

Below is a minimal, reproducible example. It’s basically just a modified version of the code to display a static image from here combined with drop down menus. In my code, I actually want to reference locally available files with PIL; I have just modified these to be URLs so it works if you run it on your machine.

import plotly.graph_objects as go
from PIL import Image

# Create figure
fig = go.Figure()

# Constants
img_width = 700
img_height = 700
scale_factor = 1.0

# Add invisible scatter trace.
# This trace is added to help the autoresize logic work.
fig.add_trace(
    go.Scatter(
        x=[0, img_width * scale_factor],
        y=[0, img_height * scale_factor],
        mode="markers",
        marker_opacity=0
    )
)

# Configure axes
fig.update_xaxes(
    visible=False,
    range=[0, img_width * scale_factor]
)

fig.update_yaxes(
    visible=False,
    range=[0, img_height * scale_factor],
    # the scaleanchor attribute ensures that the aspect ratio stays constant
    scaleanchor="x"
)

# Add image to show on load
fig.add_layout_image(
    dict(
        x=0,
        sizex=img_width * scale_factor,
        y=img_height * scale_factor,
        sizey=img_height * scale_factor,
        xref="x",
        yref="y",
        opacity=1.0,
        layer="below",
        sizing="stretch",
        source="https://raw.githubusercontent.com/michaelbabyn/plot_data/master/bridge.jpg"),
)

# Configure other layout
fig.update_layout(
    width=img_width * scale_factor,
    height=img_height * scale_factor,
    margin={"l": 0, "r": 0, "t": 0, "b": 0},
    paper_bgcolor='rgba(0,0,0,0)',
    plot_bgcolor='rgba(0,0,0,0)',
)

buttons=list([
    dict(
        args=["images", (dict(
            x=0,
            sizex=img_width * scale_factor,
            y=img_height * scale_factor,
            sizey=img_height * scale_factor,
            xref="x",
            yref="y",
            opacity=1.0,
            layer="below",
            sizing="stretch",
            source="https://raw.githubusercontent.com/michaelbabyn/plot_data/master/bridge.jpg"),)],
        label="Bridge",
        method="relayout"
    ),
    dict(
        args=["images", (dict(
            x=0,
            sizex=img_width * scale_factor,
            y=img_height * scale_factor,
            sizey=img_height * scale_factor,
            xref="x",
            yref="y",
            opacity=1.0,
            layer="below",
            sizing="stretch",
            source="https://raw.githubusercontent.com/photoprism/photoprism/develop/assets/static/img/agplv3-large.png"),)],
        label="AGPL",
        method="relayout"
    ),
])

# Add dropdown
fig.update_layout(
    updatemenus=[
        dict(
            buttons=buttons,
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.45,
            xanchor="left",
            y=1.085,
            yanchor="top",
            bgcolor="white",
        ),
    ]
)

fig.show(config={'doubleClick': 'reset',})

This user had a similar problem with dropdowns, and the solution was to go with Dash, it’s much easier to use for an interactive app.


It should be straightforward to change the code to update an image rather than a trace, but let me know if not :slight_smile:

For anyone that runs into the problem I described above, the following code for the buttons variable solves the issue

buttons = list([
    dict(label="Bridge",
         method="relayout",
         args=[{'images[0].source': "https://raw.githubusercontent.com/michaelbabyn/plot_data/master/bridge.jpg"}]),
    dict(label="AGPL",
         method="relayout",
         args=[{'images[0].source': "https://raw.githubusercontent.com/photoprism/photoprism/develop/assets/static/img/agplv3-large.png"}]),
])