✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Multi page app with tabs

Hi,
I am making a new dash app and as my content is growing I want to deploy a multipage app. I went through the tutorial and it work fine. Now I want something like this.

These tabs are used to navigate to new pages. My code looks like this.

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

import dash

app = dash.Dash()
server = app.server
app.config.suppress_callback_exceptions = True
from apps import app1, app2
app = dash.Dash()


tab_style = {
    'color': '#0074D9',
    'text-decoration': 'underline',
    'margin': 30,
    'cursor': 'pointer'
}

app.layout = html.Div([
    dcc.Location(id='url'),
    dcc.Link('Tab 1', href='/', style=tab_style),
    dcc.Link('Tab 2', href='/apps/app1', style=tab_style),
    dcc.Link('Tab 3', href='/apps/app2', style=tab_style),
    html.Div(id="page-content")
])




app.callback(
Output(component_id="page-content", component_property='children'),
             [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/apps/app1':
         return app1.layout
    elif pathname == '/apps/app2':
         return app2.layout
    else:
        return '404'


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

What is the right way to achieve it ?

Try have a look at 📣 New! Dash Tabs Component
:slightly_smiling_face:

Tab were useful but they are not continued in the further version. Even the latest rc version does not have it. I think the support is discontinued. Plus there is still no example where a full layout is fetched from another page in a tab.

Whether or not support of dcc.Tabs() are discontinued is something I will need @chriddyp to help with :slightly_smiling_face:.

You write that you need an example “where a full layout is fetched from another page in a tab.” I am not sure what you mean, is it something like this?

tab1_layout = [
	html.Div("some stuff")
]

tab2_layout = [
	html.Div("some other stuff"),
	dcc.Graph("some really cool figure stuff")
]


app = dash.Dash(__name__, server=server)

app.layout = html.Div(
	children=[
		dcc.Tabs(
			tabs=[
				{'label': 'Tab 1', 'value': 1},
				{'label': 'Tab 2', 'value': 2},
				{'label': 'Tab 3', 'value': 3}

			],
			value=1,
			id='tabs'
		),
		html.Div(id='tab-output')
	]
) 

@app.callback(
	Output('tab-output', 'children'),
	[Input('tabs', 'value')])
def show_content(value):
	if value == 1:
		return tab1_layout
	elif value == 2:
		return tab2_layout
	elif value == 3:
		return tab3_layout
	else:
		html.Div()

You should be able to give the Div’s with “some really cool stuff” in them a URL using the dcc.Location component if you need it for anything. (This is not something I have tested :man_technologist:)

1 Like

See https://dash.plot.ly/urls also this example that styles links as tabs: https://github.com/plotly/dash-vanguard-report/

1 Like

This was exactly I was looking for, Man you just saved my Day and Job. Thanks

1 Like

Lot’s of good stuff in https://dash.plot.ly, I recommend reading through all of the articles posted there

Hi all

Inspired by the vanguard report app with multiple tabs I am setting up a similar arrangement…!

I am finding that once I generate a number of plots in one tab, when I jump to the another tab, the graphics are not downloaded (started) properly, The user would have to refresh the page in that new tab to keep running the app…

has anybody found a similar issue?

Here a screenshot of the failed tab

Here how it should be looking when I go to another tab (or when I refresh the page)

here after I successfully run it!

Hi @monitorcasalab,

What I found is to follow the MVC structure while using tabs can be useful and things does not clash.
The folder structure I use is like
|-apps
|–Component Dir
|—component_controller
|—component_view
|—component_html

the view is the page that defines your view and should contains all the callbacks. and the main layout = " html""

Controller will contain all the logic. Suppose an API call you want to make.
In view do something like this

from apps.Component_Dir.component_controller import Get_data_app1

get_data = Get_data_app1()


@app.callback(
    Output("custom_fields_pie_chart", "figure"),
    [Input("custom_field_dropdown", "value")]
)
def update_custom_field_pie_chart(custom_field_dropdown):
    print(custom_field_dropdown)
    if custom_field_dropdown is None:
        raise dash.exceptions.PreventUpdate()
    else:
        return get_data.draw_custom_field_pie_chart(custom_field_dropdown)

Now get_data can be a class which can have different function for various callback

The component html contain static HTML like you want to return a
textbox when a user click a button.

from view page write a callback that will call a function on the controller that wil return an static html into the div.

Keeping everything organized will help you getting into conflicts which you are getting right now.

Hope this helps.

2 Likes

Many thanks rvsingh011

It was really messy, i have the feeling that it now runs faster,

Another thing that i found that may be also the cause of the trouble. When the app is still running ( like updating a graphic) and I click in another tab, it may cause the clicked tab not downloading properly.

:heart:ing Dash!!!

@monitorcasalab are you using my folder structure ?
as per the second part I guess it will not be an issue, although I am not sure but I did not faced this issue even when my view was under a callback changing tabs was not a problem.

Now, is it discontinued or not??

Hi,

This page is not found.

Also, I have tried to use urls to get the data clustering functionality. But no luck.

Requirement is - to create sections for each type of data so when user clicks on any section and see the respective files.
But for some reason the files from the folder are not showing up upon page click

Issue link

Any think I am doing wrong, I want to know and any other alternative.

Regards,