Change url when clicking on side menu links and tabs

Hello,

I have an app organised as follow:

  • app.py
  • pages
    |-- america_index.py
    |-- germany_index.py

app.py :

import dash
from dash import Dash, html
import dash_bootstrap_components as dbc

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

app.layout = dbc.Container([
                        dbc.Row([
                                dbc.Col(html.H1('World App')),
                                ]
                                ),
                        dbc.Row([
                                dbc.Col(
                                        dbc.Navbar(
                                                    [
                                                     dbc.Button(f"{page['name']}",
                                                                href=page["relative_path"],
                                                                color="primary",)
                                                     for page in dash.page_registry.values()
                                                    ]
                                                    ),
                                        ),
                                ]),

                        dbc.Row(dash.page_container),
                            ])


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

america_index.py:

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

dash.register_page(__name__, name= 'AMERICA', path='/')

layout = html.Div([dcc.Location(id='america_url'),
                   dbc.Col(children=[dbc.Row(html.H2(children='AMERICA')),
                                     dbc.Row(html.P(children='info_about_america')),
                                     dbc.Row(dbc.Nav(children=[dbc.Button(children='america_east_coast', id='america_east_coast_id', color='info'), 
                                                               dbc.Button(children='america_west_coast', id='america_west_coast_id', color='info')], pills=True, vertical=True))]), 
                   html.Div(id='america_page_content')])

@callback(
    Output('america_page_content', "children"),
    [Input('america_east_coast_id', 'n_clicks'),
     Input('america_west_coast_id', 'n_clicks')])

def render_page_content(*args):

    ctx = dash.callback_context

    if not ctx.triggered:
        button_id = 'america_east_coast_id'
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if button_id == 'america_east_coast_id':
        side_menu_layout = dbc.Row(
                                            dbc.Col(
                                                    [
                                                     dbc.Row(dbc.Tabs(children = [
                                                                                  dbc.Tab(label='New York', tab_id='america_east_coast_ny_id'),
                                                                                  dbc.Tab(label='Philadelphia', tab_id='america_east_coast_philly_id')
                                                                                  ],
                                                                      id = 'america_tabs',
                                                                      active_tab = 'america_east_coast_ny_id'
                                                                      )
                                                             ),
                                                    dbc.Row(html.Div(id='america_tab-content'))
                                                    ]
                                                   )
                                           )

    elif button_id == 'america_west_coast_id':
        side_menu_layout = dbc.Row(
            [
                dbc.Col(
                    [
                        dbc.Row(dbc.Tabs(children=[
                            dbc.Tab(label='Los Angeles', tab_id='america_west_coast_la_id'),
                            dbc.Tab(label='San Francisco', tab_id='america_west_coast_sa_id')
                        ],
                            id='america_tabs',
                            active_tab='america_west_coast_la_id'
                        )
                        ),
                        dbc.Row(html.Div(id='america_tab-content'))
                    ]
                )
            ]
        )

    return side_menu_layout


@callback(
    Output('america_tab-content', "children"),
    [Input("america_tabs", "active_tab")])
def render_tab_content(active_tab):
    if active_tab == 'america_east_coast_ny_id':
        tab_layout = html.Div('This is tab forecast New York')

    elif active_tab == 'america_east_coast_philly_id':
        tab_layout = html.Div('This is tab forecast Philadelphia')

    if active_tab == 'america_west_coast_la_id':
        tab_layout = html.Div('This is tab forecast LOS ANGELES')

    elif active_tab == 'america_west_coast_sa_id':
        tab_layout = html.Div('This is tab forecast SAN FRANCISCO')

    return tab_layout

germany_index.py:

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

dash.register_page(__name__, name= 'GERMANY', path='/Germany')

layout = html.Div([dcc.Location(id='germany_url'),
                   dbc.Col(children=[dbc.Row(html.H2(children='AMERICA')),
                                     dbc.Row(html.P(children='info_about_germany')),
                                     dbc.Row(dbc.Nav(children=[dbc.Button(children='germany_east', id='germany_east_id', color='info'), 
                                                               dbc.Button(children='germany_west', id='germany_west_id', color='info')], pills=True, vertical=True))]), 
                   html.Div(id='germany_page_content')])

@callback(
    Output('germany_page_content', "children"),
    [Input('germany_east_id', 'n_clicks'),
     Input('germany_west_id', 'n_clicks')])

def render_page_content(*args):

    ctx = dash.callback_context

    if not ctx.triggered:
        button_id = 'germany_east_id'
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if button_id == 'germany_east_id':
        side_menu_layout = dbc.Row(
                                            dbc.Col(
                                                    [
                                                     dbc.Row(dbc.Tabs(children = [
                                                                                  dbc.Tab(label='Berlin', tab_id='germany_east_berlin_id'),
                                                                                  dbc.Tab(label='Leipzig', tab_id='germany_east_leipzig_id')
                                                                                  ],
                                                                      id = 'germany_tabs',
                                                                      active_tab = 'germany_east_berlin_id'
                                                                      )
                                                             ),
                                                    dbc.Row(html.Div(id='germany_tab-content'))
                                                    ]
                                                   )
                                           )

    elif button_id == 'germany_west_id':
        side_menu_layout = dbc.Row(
            [
                dbc.Col(
                    [
                        dbc.Row(dbc.Tabs(children=[
                            dbc.Tab(label='Koln', tab_id='germany_west_koln_id'),
                            dbc.Tab(label='Frankfurt', tab_id='germany_west_frankfurt_id')
                        ],
                            id='germany_tabs',
                            active_tab='germany_west_koln_id'
                        )
                        ),
                        dbc.Row(html.Div(id='germany_tab-content'))
                    ]
                )
            ]
        )

    return side_menu_layout


@callback(
    Output('germany_tab-content', "children"),
    [Input("germany_tabs", "active_tab")])
def render_tab_content(active_tab):
    if active_tab == 'germany_east_berlin_id':
        tab_layout = html.Div('This is tab forecast Berlin')

    elif active_tab == 'germany_east_leipzig_id':
        tab_layout = html.Div('This is tab forecast Leipzig')

    if active_tab == 'germany_west_koln_id':
        tab_layout = html.Div('This is tab forecast Koln')

    elif active_tab == 'germany_west_frankfurt_id':
        tab_layout = html.Div('This is tab forecast Frankfurt')

    return tab_layout


I would like the url to display http://127.0.0.1:8050/america/east_coast/ny on the landing page of the app and then the urls to change to the selected side menu button and tab like this:
http://127.0.0.1:8050/america/east_coast/philly
http://127.0.0.1:8050/america/west_coast/la
http://127.0.0.1:8050/america/west_coast/sa
http://127.0.0.1:8050/germany/east/berlin
http://127.0.0.1:8050/germany/east/leipzig
http://127.0.0.1:8050/germany/west/koln
http://127.0.0.1:8050/germany/west/frankfurt

I’ve tried a lot of variations using the “pathname” and Location components but I didn’t manage: I get lots of 404 page not found errors.

Could someone please point me in the right direction?

Thank you very much.