Cross filters on different tabs

Hello! I have same filters on different tabs (dates and dropdowns). How I can bound them so that when you change the filter in one tab, this change will also pass to the rest?

Hi @Kirrango

sounds like pattern matching callbacks could work for you.

Hi,
Maybe this can be a reference for you.

@AIMPED @stu Thanks you all, guys! I will check it and write after :slight_smile:

Hey, I tried this method, but caught the following error:

Overlapping wildcard callback outputs

In the callback for output(s):
  datasets2.data
  {"index":ALL,"type":"date"}.value
Output 1 ({"index":ALL,"type":"date"}.value)
overlaps another output ({"index":1,"type":"date"}.value)
used in a different callback.

I give to all my date filter id like {'type': 'date', 'index': 1} and use it in Output {"index":ALL,"type":"date"}, but they are used also on their tabs, and that’s why I got this error due to multiple accesses to the same element :smiling_face_with_tear:

Hi, thanks for reply, but, I think, it can’t help in my case : (

Hello @Kirrango,

Is it possible to have the filters be outside of the tabs instead? You could use an offcanvas element if necessary.

That way, instead of trying to emulate the filter changes, there is only one set of filters to alter.

Hello, I thought about it but then I will have to change the dashboard design, which is unacceptable (

Is it possible to see more of whats going on with your code then?

The problem with updating filters with the same value and listening for a value event, could very easily lead to circular callbacks.

Do you have a screen shot of your current layout and I’ll see if there is a way to have the overarching filters stay in the same position?

I have 3 tabs, they are at the very top
And I have 8 filters on this tab for example. I need to save first two (first two filters on the first row). At the rest pages I have these two filters too.

First, I like your layout, its very nice looking.

Second, it looks like you have one overall filter and then the second set of filters is tab specific, is that correct?

You could use position arguments to help out, like this:

import dash_bootstrap_components as dbc
from dash import html, Dash

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

tab1_content = dbc.Card(
    dbc.CardBody(
        [
            html.P("This is tab 1!", className="card-text"),
            dbc.Button("Click here", color="success"),
        ]
    ),
    className="mt-3",
    style={'position':'absolute', 'top':'10vh'}
)

tab2_content = dbc.Card(
    dbc.CardBody(
        [
            html.P("This is tab 2!", className="card-text"),
            dbc.Button("Don't click here", color="danger"),
        ]
    ),
    className="mt-3",
    style={'position':'absolute', 'top':'10vh'}
)


tabs = html.Div([dbc.Tabs(
    [
        dbc.Tab(tab1_content, label="Tab 1"),
        dbc.Tab(tab2_content, label="Tab 2"),
        dbc.Tab(
            "This tab's content is never seen", label="Tab 3", disabled=True
        ),
    ]),
    html.Button('testing', style={'position':'absolute', 'top':'5vh'})
]
)

app.layout = tabs

app.run(debug=True, port='12345')

Notice how the button is outside of the tabs, but still listed above the tab-content when displayed.

You could even use a css style sheet instead of hard coding the tabs, and use:

.tab-content {
     position: absolute;
     top: 7vh: /* use this to get your tab content in the right spot */
}

result:

image

Its not perfect, but will keep you from having to redesign the layout. Unfortunately, tabs dont use callbacks by design, otherwise you could query a dcc.Store of the filters before loading the tab-content.

1 Like

Alternatively, you could use flex to fit the filter above without having to mess with the height element:

image

css

#tabHolder {
    display: flex;
    flex-direction: column;
    align-items: stretch;
}

.tab-content {
    display: flex;
    order: 2;
    flex-grow: 1;
}

app:

import dash_bootstrap_components as dbc
from dash import html, Dash

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

tab1_content = dbc.Card(
    dbc.CardBody(
        [
            html.P("This is tab 1!", className="card-text"),
            dbc.Button("Click here", color="success"),
        ]
    ),
)

tab2_content = dbc.Card(
    dbc.CardBody(
        [
            html.P("This is tab 2!", className="card-text"),
            dbc.Button("Don't click here", color="danger"),
        ]
    ),
)


tabs = html.Div([dbc.Tabs(
    [
        dbc.Tab(tab1_content, label="Tab 1"),
        dbc.Tab(tab2_content, label="Tab 2"),
        dbc.Tab(
            "This tab's content is never seen", label="Tab 3", disabled=True
        ),
    ]),
    html.Button('testing', style={'display':'flex', 'order':1})
],
    id='tabHolder'
)

app.layout = tabs

app.run(debug=True, port='12345')
1 Like

Hmm, thanks for the rating and reply!

Yes, I have two sets of filters: first don’t change in all tabs and second are specific for every tab. I think, I need to try taking filters outside the tab and configuring them through flex. I did it with the color filter and it works great.

But do you think there is no more elegant solution to this problem through dcc.Store or other? I thought about VERY crutch solution like dcc.Store for every tab and save timestamp of last filter changing. There were also thoughts about saving values to a dictionary or database, but it is unreasonably difficult for such task.

A dcc.Store is basically a dictionary, so you can use it whenever.

You’d only need one dcc.Store in the overall layout.

You can use the tabs β€œactive_tab” to trigger a callback in order to populate the filters from the dcc.Store, then on filter change of the active tab (no way to go alter the non-visible filters from user interface), but you populate the dcc.Store based on those filters.

Then as you navigate, the filters will get updated on load. You would need to utilize pattern-matching MATCH in order to trigger the updates and push the updates back to the filters either using MATCH or ALL, that would be up to you.

I actually prefer the flex option for right now, but may change my opinion later. It keeps it easier to use, only one callback and no pattern-matching. If you try to push all the filters values to the filters immediately, you will trigger multiple callbacks. It may not be an issue now with 3 tabs, but if you expand to more tabs, it will continue to grow. :stuck_out_tongue:

1 Like

Thanks for your opinion. So I will try flex option and write about result later :blush:

1 Like