Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

CallBacks A way to get a list of the Outputs Id or a static variable for the function

Hello!
so the problem is this:
I am creating a generic Callback that goes as follows:

# create the callback for the page path
    x = [Output(f"sideMenuSection{Section.buttonCount}Title", "style"), [Output(f"page-{name}-link", "active") for name in pages]]
    outputList = [*chain(*(e if isinstance(e, list) else [e] for e in x))]
    # Path Callback
    app.callback(
        outputList,
        [
            Input("url", "pathname"),
            Input(f"sideMenuSection{Section.buttonCount}Title", "style")
        ],
    )(toggle_active_links1)

The Function toggle_active_links1 is in the following code:

def toggle_active_links1(pathname, style, names):
    print(names)
    pathList = [pathname == name for name in names]
    if True in pathList:
        return pathList.insert(0,style)
    else:
        return pathList.insert(0,style)

I do not have an input for names! that is because I have no way of getting dynamically the names from any input in my app, now the names are in the list of outputs I have in the callback.

I see 2 options that I have no idea how to do both of them and am not sure if they’re possible:

  1. Somehow get a list of the Outputs inside the function and from here it’s easy to find the list of names I need.

  2. create a static variable somewhere in the file for each object I create maybe even creating a class for each toggle_active_links1 I create and try that. it just sounds so inefficient and also I have no idea if that’s possible or would work.

What do you guys think? How can i go on from here?

I am not sure if I understood what are the problems you want to solve, but I will assume that pages refer to different pages in a multi-page app and you want to highlight the page you are currently in in some sort of NavBar or equivalent.

One simple way to do that is to use pattern-matching callbacks and add ids to support it in your “links”. What I have in mind is something like this:

import dash
from dash.dependencies import Input, Output, State, ALL
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash(external_stylesheets=[])

app.layout = html.Div(
    [
        dcc.Location(id='url', refresh=False),
        html.Div(
            [
                # Note that ids are now dicts
                html.A(id={"type": "navlink", "index": "home"}, children='Home', href='/'),
                html.A(id={"type": "navlink", "index": "a"}, children='Page A', href='/a'),
                html.A(id={"type": "navlink", "index": "b"}, children='Page B', href='/b'),
            ],
        ),
        html.Div(id="content-page"),
    ]
)

@app.callback(
    Output('content-page', 'children'),
    Output({'type': 'navlink', 'index': ALL}, 'style'),
    Input('url', 'pathname'),
    State({'type': 'navlink', 'index': ALL}, 'href')
)
def update_path(pathname, hrefs):
   # match only current href
    style_list = [ {'color': "red"} if href == pathname else {'color': "black"} for href in hrefs]

    if pathname == "/a":
        _layout = html.H1("Page A")
    elif pathname == "/b":
        _layout = html.H1("Page B")
    else:
        _layout = html.H1("Home")

    return _layout, style_list


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

I think the same logic can be used for dynamic components that are not pages, just by adapting the Input part in the callback to something that triggers the change.

Hope that helps!

I found a simpler solution which is to use dash.callback_context.outputs_list
to get a list of the outputs.