How does dcc loading target components works?

Hi Guys,
I have multiple dropdown menu, I want the loading on those dropdown until all the options have been loaded for its and above dropdowns.
I am using dcc.Loading target_components property but unable to achieve the same.

I am using dash==2.18.2.

Layout::

app = dash.Dash(__name__)
app.css.config.serve_locally = True
app.config.suppress_callback_exceptions = True

layout = html.Div(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-1",
                                )
                            ],
                            id='loading-1'
                        )
                    ]
                ),
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-2",
                                )
                            ],
                            id='loading-2',
                            color='#c00',
                            target_components={
                                "dd-2": "options"
                            }
                        )
                    ]
                ),
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-3",
                                )
                            ],
                            id='loading-3',
                            color='#c00',
                            target_components={
                                "dd-2": "options"
                            }
                        )
                    ]
                ),
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-4",
                                )
                            ],
                            id='loading-4'
                        )
                    ]
                ),
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-5",
                                )
                            ],
                            id='loading-5'
                        )
                    ]
                ),
            ]
        )
    ]
)

app.layout = html.Main([layout])


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

callback file::

from dash import html, dcc
import dash_bootstrap_components as dbc
from dash import Output, Input
import plotly.express as px
import dash
import time




@dash.callback(
    Output("dd-2", "options"),
    [Input("dd-1", "value")]
)
def test_1(values):
    print(f"test_1: values => {values}")
    time.sleep(5)
    
    op = ["New York City", "Montreal", "San Francisco"]
    
    return op

Hi @mikeyfireball7 and welcome to the Dash community :slight_smile:

The dcc.Loading component shows the spinner based on the loading status of the children of that component.

If you want to use the target prop to trigger when a certain component in the children is loading, it would look like this:

dcc.Loading([
     dcc.Dropdown(id="dd-1"),
     dcc.Dropdown(id="dd-2"),
     dcc.Dropdown(id="dd-3")
], target_components={"dd-2": "options" })

@AnnMarieW
Thank You.

but problem with this approach is, It’s single loader and will load completely with all the children based on target components.

My Scenario is more like I have multiple dropdown menus, I want to load the dropdown based on the other dropdown.

is it possible in dash?

Yes, this is possible to have chained callbacks in Dash. I’m not 100% clear on what you are trying to do. Can you include a minimal example or some type of mock-up of how you want it to look?

Hi @AnnMarieW ,
I have this multiple dropdown each of those have dynamic options based on the user selection on the previous dropdown menu. Since It’s dynamic and I am fetching data from a database, It takes little bit time to load the dropdown menus.

scenario:
Let’s suppose I have 3 dropdown menus each is chained with the previous dropdown menu when user select the value from dropdown_1, I want all the other dropdown to be in loading state until they have the data. so in this scenario It would be like, when user selected a value from dropdown_1 then dropdown_2, dropdown_3 should be in loading state, and when dropdown_2 options are loaded it will be in unloading state but since dropdown_3 has not loaded this options It would still be in loading state until its options are loaded

It just depends on how you set up your callbacks

In this example, when you select a value from dropdown 1 then options for 2 and 3 show loading
If a user selects a value from dropdown 2 then it updates options for dropdown3 which shows loading.

import time
from dash import Dash, Input, Output, callback, dcc, html
import dash_bootstrap_components as dbc

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP], prevent_initial_callbacks=True)



app.layout = html.Div(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-1",
                                )
                            ],
                            id='loading-1'
                        )
                    ]
                ),
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-2",
                                )
                            ],
                            id='loading-2',
                            color='#c00',
                            target_components={
                                "dd-2": "options"
                            }
                        )
                    ]
                ),
                dbc.Col(
                    [
                        dcc.Loading(
                            [
                                dcc.Dropdown(
                                    ["New York City", "Montreal", "San Francisco"],
                                    multi=True,
                                    id="dd-3",
                                )
                            ],
                            id='loading-3',
                            color='#c00',
                        )
                    ]
                ),

            ]
        )
    ]
)


@callback(
    Output("dd-3", "options", allow_duplicate=True),
    Output("dd-2", "options"),
    Input("dd-1", "value"),
    prevent_initial_call=True
)
def test_1(values):
    time.sleep(5)
    op = ["New York City", "Montreal", "San Francisco"]

    return op, op



@callback(
    Output("dd-3", "options"),
    Input("dd-2", "value"),
    prevent_initial_call=True
)
def test_1(values):
    time.sleep(5)
    op = ["New York City", "Montreal", "San Francisco"]
    return op

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