Dash pages, How to get the active page URL in the page_registry dictionary

Hi community, two questions in one day, having a bit of a hard time with dash pages.

I have an app with the following menu

Header

Body

Footer

The footer stays the same, the body changes every time we switch a page.
now the header stays almost the same but also changes every time we change a page for this example let’s leave it simple and say the header gets an argument of title, every page has a different title.

so in the code, I need to pass it like this

header(dash.page_registry['active page']['header_title']

I know how to save arguments in the page_registry, but I don’t know which key to use. is there some kind of variable that contains the active path? (a callback to change the header every time the URL changes kind of destroys the purpose of dash pages.)

any idea how to get the active URL?

Hello @Matan,

Sure, you can use a dcc.Location to get the active url, from there you will have to figure out how to map it.

I’d use a header container div and update its children on every change of the url. You can even set up a dictionary with your pathnames if you want.

Scroll down to the section without pages.

@jinnyzor I said in my question that using callback to update the header will destroy the purpose of dash pages, I want to know if there’s a way to get the active page from the dash.registery.

@AnnMarieW, is this something that is possible?

@Matan, you don’t have to update the header every time, but I understand you being against this option.

I would have a callback listening to id _pages_location which is the internal location item that is used for pages. Whenever the path changes, you can compare it to the paths in the page registry to find the header and return it.

Output('header', 'children'),
Input('_pages_location', 'path')

@raptorbrad First, didn’t know _pages_location is an option so thanks!
Second, i would still prefer another way, one that involves dash.registery

Hi @Matan

If you are trying to update a component in the layout of app.py based on the URL, then yes, you would have to use a callback.

However, in this case, it would be better to put this header component in the layout of each page. Now of course, you don’t want to repeat the code (except for the title) on every page. It’s a best practice to put shared functions, components, variables etc in a utility file and import them where needed.

Here’s an example:

utils.py


def header(title):
    return dbc.NavbarSimple(
        dbc.DropdownMenu(
            [
                dbc.DropdownMenuItem(page["name"], href=page["path"])
                for page in dash.page_registry.values()
                if page["module"] != "pages.not_found_404"
            ],
            nav=True,
            label="More Pages",
        ),
        brand=title,
        color="primary",
        dark=True,
        className="mb-2",
    )

pages/historical_analysis.py

from utils import header

layout = html.Div(
    header("Historical Analyisis")
    #... rest of layout
)

app.py

app.layout=html.Div([dash.page_container, footer])

I hope this helps - I’ll add an example to the multi-page-apps-demos shortly.

1 Like

I see We have a folder of utils and components and we knew about the option to use callback we were hopeful that there was a way to avoid the callback, but if there is none, then we will use the callback :stuck_out_tongue_winking_eye:

@Matan,

There are no callbacks in the method I recommended. You simply import the component on each page and call it with the page specific data from the layout of each page.

For example - in `home.py:

from utils import header

layout = html.Div(
    header("My Home Page")
    #... rest of layout
)

No callback.

@AnnMarieW this option is a bkt problamatic for me because i have a some static data in the header which is kind of annoying to get again in every page, in my case a callback was a better solution. But thanks for the help.

Not to necro this thread, but I have a similar but not identical question.

I have a multi-page app using dash.page_registry. Outside of the dash.page_container is a dropdown and a number of tabs (using dbc.Navlink) linking to each page.

My issue is that I need the dropdown options to change depending on which page is active. The easiest way to do this, as suggested by OP, would be to be able to access some dash.page_registry[‘active’] value in my dropdown callback. Is this possible? If not, is there any way for me to get the current page/url in the dropdown callback?

Note: I tried using dcc.Location and a callback with

Input('_pages_location', 'path')

but it didn’t work (because I am not using dcc.Link?).

Suggestions would be appreciated.

Nevermind. I figured out a different way to do it- although it may not be the right or best way when working with pages.

First, I added these components to my layout:

dcc.Location(id='current-page', refresh=False),
html.Div(id='hidden')

Then I added these two lines:

Output('hidden', 'children'), 
Input('current-page', 'href'),

to my existing dropdown callback:

@callback(
     Output("year-dropdown", "options"),
     Output("year-dropdown", "value"),
     Output('hidden', 'children'),
     Input("year-dropdown", "value"),
     Input('current-page', 'href'),
)
def dropdown(year, page):
   ....
   
return year_options, year_value, current_page

Now I can use the input ‘page’ value to set the value of ‘year_options.’