Update Image carousels using Callbacks

  1. Is there a way to add image carousels in a Dash Application? I didn’t see any component in Dash Libraries that would work.

  2. I’d like to add a carousel to Modal pop-up. Would this be possible to do?

Hi @keval

There is an image carousel in the latest release of Dash Bootstrap Components v0.13.0. Here is the announcement:

1 Like

@AnnMarieW Is there an example you can share that updates the items property of the carousel from callback? I didn’t see it in the docs.

Hi @keval

Currently the items prop can’t be updated once the Carousel is animating. This may be a bug - I’ll investigate.

The workaround is to return an updated Carousel to the children prop of an html.Div. Here is a mwe:


import dash
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import dash_html_components as html

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.DARKLY])

img_style = {"height": "600px", "width": "800px"}
img1 = "https://user-images.githubusercontent.com/72614349/128213790-aaebac53-2e6d-4d20-a41d-647dc0a563d3.jpg"
img2 = "https://user-images.githubusercontent.com/72614349/128213795-e0eff265-2bda-48c7-b89b-0863dd582650.jpg"
img3 = "https://user-images.githubusercontent.com/72614349/128213796-7d660ce6-3e63-4c53-8cf1-dab33ba1b514.jpg"
img4 = "https://user-images.githubusercontent.com/72614349/128245336-faae1bd9-47bb-404c-b8f2-7c94ad981222.jpg"

carousel1 = dbc.Carousel(
    items=[{"key": "1", "src": img1}, {"key": "2", "src": img2}],
    controls=True,
    indicators=True,
    style=img_style,
)

carousel2 = dbc.Carousel(
    items=[{"key": "3", "src": img3}, {"key": "4", "src": img4}],
    controls=True,
    indicators=True,
    style=img_style,
)

app.layout = dbc.Container(
    [
        dbc.Row(
            dbc.Col(
                [
                    dbc.Button("Change slideshow", id="toggle", n_clicks=0),
                    html.Div(id="carousel"),
                ]
            )
        ),
    ],
    fluid=True,
)


@app.callback(
    Output("carousel", "children"), Input("toggle", "n_clicks"),
)
def update_carousel(n):
    if n % 2 > 0:
        return carousel2
    return carousel1


if __name__ == "__main__":
    app.run_server(debug=True)

Thanks @AnnMarieW

For context, here’s my use case.

I have a bunch of geo-location, represented by black-dots in the attached GIF. Upon clicking each dot, a modal pop-ups with information about the location. I have added a image carousel (currently static images) to the modal pop-up.

dash-modal-img (1)

I’d like these to be dynamic based on the location.

dbc.Modal(
                    [
                        dbc.ModalHeader("Lease Information", style={"color":"white"}),
                        dbc.ModalBody(
                            [

                                # Images
                                dbc.Carousel(

                                    id="images",
                                    items=[
                                        {"key": "1", "src": "https://gmaps-images"},
                                        {"key": "2", "src": "https://gmaps-images"},
                                        {"key": "3", "src": "https://gmaps-images"},
                                    ],
                                    controls=True,
                                    indicators=True,
                                ),

                                dbc.Label("Address:", style={"color":"white", "margin-right":"10px"}),
                                dbc.Label("Address:", id="Address"),
                                html.Br(),

                            ]
                        ),
                        dbc.ModalFooter(
                            [
                                dbc.Button("OK", className="mr-1"),
                            ]
                        ),
                    ],
                    id="modal-1",
                ),

Say, we have a dictionary of location and associated images

img_dict = {'location 1': ['link to img1', 'link to img2'], 
                  'location 2': ['link to img3', 'link to img4'] }

Now, I’d like to populate the items property of the dbc.Carousel from the callback, where the input to the callback function is click event and it looks up the values (images) of the location in the img_dict

@application.callback([
                                 Output("modal-1","is_open"),
                                 Output("carousel-1", "items"),
                               ],

                               [
                                Input("map-graph","clickData"),
                                Input("close","n_clicks")
                               ],

                               [
                                State("modal-1", "is_open")
                              ],
                    )
def update_carousel(clickData, modal_close, is_open): 

     # click event for black dots on map-graph
     if clickData:

        res = json.dumps(clickData, indent=2)

        Address = clickData["points"][0]["customdata"]["Address"]
        
        list_of_images = img_dict[Address] 

        return (Address, list_if_images)

Is this currently possible to do? The workaround you have will require dbc.Carousel object for each point/location on the map which could be into 100s.

Hi @keval I don’t understand the callback you posted - are there typos? There is no @app.callback and it looks like the return is only if clickData is None?

But I think this callback should work per the mwe I posted. Try putting a html.Div(id="carousel") in the dbc.ModalBody(...) instead of dbc.Carousel(...).
Then in the callback change
Output("carousel-1", "items"),
to:
Output(“carousel”, “children”),

then include in the callback function:

carousel = dbc.Carousel(
    items=img_dict[Address]
    controls=True,
    indicators=True,    
)
return Address, carousel

@AnnMarieW

Sorry about the typos. I was trying to minimize the number of lines of code for simplicity.

The callback should make sense now. Basically, I’d like to pass a list of string of images to items property of the dbc.Carousel.

I’ll try your recommended approach.

ok, and be sure that items is formatted correctly for the Carousel. It needs to be a list of dicts like the following. It does’t look like img_dict[Address] does that.

items=[
    {"key": "1", "src": "https://gmaps-images"},
    {"key": "2", "src": "https://gmaps-images"},
    {"key": "3", "src": "https://gmaps-images"},
],
1 Like

@AnnMarieW

More of a general question but related to constructing list of dicts for carousel.

Is there a way to pass data / objects between the callbacks? I have used dcc.Store to store the value of inputs.

However, in this case, I am constructing a dictionary (for items property of carousel) in a different callback, but would like to reference it / do lookup in a separate callback.

How would you recommending doing something like that? Ideally, would like to not rewrite the code and reuse constructed objects like DataFrames, dictionaries, lists etc.

@keval Yes, using dcc.Store is the recommended way to share data between callbacks. This should work well. A dictionary can be stored in the data property of the dcc.Store

Hi @Reinger and welcome to the Dash community :slightly_smiling_face:

Rather than using the Carousel, it sounds like you are looking for a before and after image slider. If so check out this post: Image slider in Dash - #14 by Emil

You can find this component in @Emil’s Dash Extensions library

A post was split to a new topic: Storing a DataFrame in dcc.Store