dash-bootstrap-components icon indicating copy to clipboard operation
dash-bootstrap-components copied to clipboard

Unable to pass dbc components into callbacks instead of component id

Open kszlim opened this issue 3 years ago • 6 comments

Before opening:

Please fill out the below information as much as possible.

  • dash version: 2.4.1
  • dash-bootstrap-components version: 1.1.0
  • components affected by bug: n/a

What is happening?

Unable to use this feature of dash components https://dash.plotly.com/basic-callbacks#passing-components-into-callbacks-instead-of-ids due to Tab not auto-generating a useful id, when you operate on a callback with the "active_tab" property, you end up getting "tab-n", but that isn't exposed on the tab objects themselves under tab_id or id.

kszlim avatar Jun 24 '22 23:06 kszlim

I think the fix to this would be to auto-generate a tab_id for Tab objects in the case that it's not explicitly defined.

kszlim avatar Jun 27 '22 18:06 kszlim

Hey @kszlim

Could you share a code snippet that demonstrates the problem you're having? What specifically are you trying to do that you are currently not able to?

tcbegley avatar Jun 29 '22 13:06 tcbegley

There's no tab_id property

app.layout = dbc.Container(
                       TABS := dbc.Tabs(
                          children=[
                              TAB_1 := dbc.Tab(label="tab_1"),
                              TAB_2 := dbc.Tab(label="tab_2")
                           ]
                         ],
                         dbc.Row([TABS_CONTENT := html.Div()])
                      )

@callback(
    Output(content, "children"),
    Input(TABS, "active_tab"),
)
def render_tabs_content(active_tab):
    if active_tab == self.TAB_1.tab_id:
        return html.Div()
    elif active_tab == self.TAB_2.tab_id:
        return html.Div()
    else:
        pass

I then get the error, this doesn't work if I use id either. Essentially, the child Tab objects of Tabs don't have any identifier that I can match against.

AttributeError: 'Tab' object has no attribute 'tab_id'

kszlim avatar Jun 29 '22 17:06 kszlim

@tcbegley is that example good enough?

kszlim avatar Jul 12 '22 19:07 kszlim

Hi @kszlim,

Apologies for slow response getting back to you. This is a project I maintain in my spare time which I haven't had much of the last few weeks.

Thanks for the example. I think the best fix is to manually specify tab_id when you create the tab (see below). This seems to let the app run without error.

The Tab does actually create a default tab_id, but it does so on the javascript side which is only executed once the app is running and accessed in the browser. This is necessary because the default value depends on how many other tabs and the order, so the parent Tabs component collects each Tab and assigns a tab_id. Unfortunately with the use case you have, the tab_id is required to specify callbacks before the app starts running leading to this problem.

While the manual specification of the tab ids is a little bit annoying, hopefully it's not too onerous and lets you continue to use components instead of component ids as you want :)

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

app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container(
    [
        TABS := dbc.Tabs(
            children=[
                TAB_1 := dbc.Tab(label="tab_1", tab_id="tab-1"),
                TAB_2 := dbc.Tab(label="tab_2", tab_id="tab-2"),
            ]
        ),
        dbc.Row([TABS_CONTENT := html.Div()]),
    ],
)


@callback(
    Output(TABS_CONTENT, "children"),
    Input(TABS, "active_tab"),
)
def render_tabs_content(active_tab):
    if active_tab == TAB_1.tab_id:
        return html.Div()
    elif active_tab == TAB_2.tab_id:
        return html.Div()
    else:
        pass


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

tcbegley avatar Jul 31 '22 08:07 tcbegley

Thanks, so there's no chance the implementation is going to change to pre-create the id in the backend?

I can deal with the workaround, but I think it'd be nice if dbc tabs work like most other dash components and have an auto-generated uuid that's referenceable in the backend.

kszlim avatar Aug 29 '22 22:08 kszlim