Passing URL querystring to callback

In my dash app I can pass the **kwargs to layout components like dropdown in a following manner:

def dropdown1(**kwargs):
    return dbc.Col(
        dcc.Dropdown(
            id='dropdown1',
            options=options_dropdown(),
            value=kwargs.get("value1"),
        ) )

All the following dropdowns in my app are dependent on chosen value in the first dropdown. The callback(s) for those dropdowns would always override their respective kwargs in the layout.

I tried to pass **kwargs to callback like:

@callback(
    Output("dropdown2", "options"),
    Output("dropdown2", "value"),
    Input("dropdown1", "value"),
    prevent_initial_call=False
)

def update_dropdown2 (dropdown1_value, **kwargs):
    if not dropdown1_value:
        return [], []
    
   dropdown2_kwarg = kwargs.get('value2')
    if dropdown2_kwarg is not None:
        dropdown2_kwarg = dropdown2_kwarg [0] 

    dropdown2_opts = get_dropdown2_opts(dropdown1_value)
    all_values = [option['value'] for option in dropdown2_opts]
    
    if dropdown2_kwarg is not None:
        return All_strenght_opts, [dropdown2_kwarg]
    
    return dropdown2_opts, all_values

This does not work either. Also, with Input(‘_pages_location’, ‘path’), I get

Property “path” was used with component ID: “_pages_location” in one of the Input items of a callback. This ID is assigned to a dash_core_components.Location component in the layout, which does not support this property.

Also tried

@callback(
    Output("dropdown2", "options"),
    Output("dropdown2", "value"),
    Input("dropdown1", "value"),
    Input('_pages_location', 'pathname'),
    prevent_initial_call=True
)

def update_dropdown2 (dropdown1_value, path):
   
  
    parsed_url = urlparse(path)
 
    query_params = parse_qs(parsed_url.query)
 
    Dropdown2_kwarg = query_params.get('phase')

but the returned kwarg is None eventhough it’s present in URL

Hello @davzup89,

I believe that you are looking for search from the _pages_location.

https://dash.plotly.com/dash-core-components/location

You’ll need to parse it out into the keywords because it just gives you the raw string.

Something like mentioned here could work:

Thanks!

‘search’ was it.

I am already parsing this way:

parsed_url = urlparse(path)

query_params = parse_qs(parsed_url.query)
2 Likes

I found out as long as the URL is present in the browser, the dropdown values would now revert to those in URL instead of previously defined callback behavior.
This is quite problematic because I would only want to filter dropdowns with URL when the URL is first sent (when enter is press in the browser input field). I though using Input instead of State with _pages_location would do that but apparently not.
Is this kind of behavior achievable with Dash?

I guess, the search would need to revert back to None/null after being used for that.

    parsed_url = urlparse(path)
    query_params = parse_qs(parsed_url.query)
    value_kwarg = query_params.get('value')
    
    if value_kwarg :
        value_kwarg = value_kwarg[0].split(',')

    All_sets = options_dropdown(inputs)
    
    if value_kwarg:
        return All_sets, value_kwarg
    
    return All_sets, [All_sets[-1]["value"]] if All_sets else []

You should be using ctx.triggered to figure out what is changing.

Also, if you are changing the pathname directly when crafting, you will always be triggering it.

What you can do is merge the callbacks and use the ctx.triggered to keep the callbacks from becoming circular.

Another thing you can do, is to make sure the built query string doesn’t equal the current query string, if so, do no update.

1 Like

Hmm, does changing url indeed trigger the callback via Input(‘_pages_location’, ‘search’)?

Because with my code I get empty dropdown if trying to pass kwargs from URL. Snippets below:

    if not ctx.triggered:
        return [], []

    triggered_id, triggered_prop = ctx.triggered[0]["prop_id"].split(".")
  
    if triggered_id == '_pages_location' and value_kwarg:
        return All_opts, value_kwarg
    elif triggered_id == 'dropdown1':
        return All_opts, all_values

I believe that changing the string triggers the layout being loaded again.

Place a print in the layout to verify. :slight_smile: