Giter Club home page Giter Club logo

dash-multi-page-app-demos's Introduction

Dash pages multi-page app demos

This repo contains minimal examples of multi-page apps using the Pages feature available in dash>=2.5.1

See the ๐Ÿ†• Dash Documentation Multi-Page Apps and URL Support

๐ŸŽฅ Don't miss the video tutorials:

This feature was developed in dash-labs. For background, see the thread on the Dash Community Forum. If you have a multi-page app using the pages plugin from dash-labs, see the post on how to migrate to dash>=2.5.1.

I hope these examples help you get started exploring all the cool features in Pages. If you find this project helpful, please consider giving it a โญ


Example Apps

The examples are listed by their folder name.

  1. multi_page_basics/ - minimal overview of basic pages features.
  2. multi_page_pathname_prefix/ - overview using a pathname prefix.
  3. multi_page_cache/ - sharing data between pages (update-- example removed - please see examples #4 and/or #11)
  4. multi_page_cache_background_callbacks - Background callbacks (long callback) with caching - adapted for multi-page apps from the dash docs examples.
  5. multi_page_example1/ - 3 page app with header navbar, graphs and callbacks. Uses dash-bootstrap-components.
  1. multi_page_flask_login/ - uses flask-login to secure one page of a multi-page app. See 2 versions of this app!
  2. multi_page_layout_functions/ - uses a function to access dash.page_registry from within the pages folder to build a sidebar.
  3. multi_page_meta_tags/ - how images are used in meta tags when sharing the app on social media.
  4. multi_page_nested_folder/ - creates a sidebar from a sub folder in the pages folder and adds arbitrary data to dash.page_registry. Uses dash-mantine-components
  5. multi_page_query_strings/ - passes variables to the layout function from the url query string. Also shows how to use dcc.Link within a dcc.Markdown
  6. multi_page_store/ - sharing data between pages with a dcc.Store.
  7. multi_page_table_links/ - uses links in a DataTable and an html table for navigation and passes variables from the pathname to the page layout function.
  8. multi_page_sync_components/ - Two examples. The first is a simple example, the second syncs components between pages using MultiplexerTransform from dash-extensions to update a dcc.Store from multiple callbacks.
  9. multi_page_theme_switch/ - demos a light and dark theme switch component from the dash-bootstrap-templates library.
  10. multi_page_update_url_in_callback/ - page navigation via callback - shows how to update dcc.Location (refreshes page) or a dcc.Link (doesn't refresh page).
  11. multi_page_update_url_from_figure/ - page navigation via updating a link when clicking on a figure.

Other tutorials or examples using pages:

  1. Adding a Blog to your Dash app. See this Dash Community Forum post. It describes how to do this and includes this repo from @bradley-erickson.

  2. See the Dash Webb Compare app live. This app shows the first images from the James Webb Space Telescope. Compare before and after images of Hubble vs Webb. The Github repo has 2 versions of the app using pages.

    • app_pages.py - Creates an multi-page app without using the pages folder.
    • app_pages_no_assets.py - This multi-page app uses images that are hosted on GitHub so it doesn't use either the pages or the assets folder.

Tips and Tricks

  1. Pretty print dash.page_registry - with the print_registry() function from dash-labs
  2. How to use dcc.Link in Markdown - for high performance page navigation from a link in a dcc.Markdown component.
  3. Avoiding duplicate ids - Strategies for handling ids in a large multi-page app.
  4. Display loading screen when page_container is loading - Shows how to make the overall loading screen only display when there is a change to the _pages_content that involves a layout being changed and not changes within the layout.


Example Apps

This folder has a minimal overview of the basic pages features, including:

  • setting the default home page
  • handling variables in the pathname
  • updating the app title and description with a function
  • handling variable in query strings
  • setting redirects
  • adding extra data to the dash.page_registry
  • customizing the dash.page_registry defaults
  • how images are added to meta tags
  • adding pages without using the pages folder

The image below ๐Ÿ‘‡ is from the path_variables page. Note that asset "inventory" and department "branch-1001" are passed from the pathname to the layout function and are displayed on the page.

basics


This example shows how to use the relative_path attribute in dash.page_registry in deployment environments that use a pathname prefix. It also shows use of dash.get_asset_url() to get the correct path to the assets folder from a file in the pages folder.

  • relative_path: The path with requests_pathname_prefix prefixed before it. Use this path when specifying local URL paths that will work in environments regardless of what requests_pathname_prefix is. In some deployment environments, like Dash Enterprise, requests_pathname_prefix is set to the application name, e.g. my-dash-app. When working locally, requests_pathname_prefix might be unset and so a relative URL like /page-2 can just be /page-2. However, when the app is deployed to a URL like /my-dash-app, then relative_path will be /my-dash-app/page-2.

Note the /app1/ pathname prefix in the url ๐Ÿ‘‡

pathname_prefix


Example removed - please see #11 multi_page_store and #4 multi_page_cach_background_callbacks.


This example shows how to use caching and background callbacks in a multi-page app. The examples in the dash docs needed to be modified to make it possible to switch pages while background callbacks are running.

This example shows a small app with three pages with callbacks. Each page displays a figure. It uses dash-bootstrap-components with dbc.DropdownMenu to display the links in a navbar.

This example is the multi_page_example1 app with HTTP Basic Auth from the dash-auth` package. Basic Auth section of the dash docs.

Example1

You will find two similar examples.

  1. multi_page_flask_login/ - original example
  2. multi_page_flask_login2/ - the new and improved version contributed by @jinnyzor. See this Dash Community Forum post for more information

For other authentication options see:

flask__login


This app demonstrates how to create a sub-topics sidebar that is only used in certain pages. It shows how to use functions to access the dash.page_registry from within the pages folder after it's finished building. For more details see also: https://dash.plotly.com/urls#dash-page-registry

This app shows more details on how the images are added to the meta tags. See also the Dash Documentation: https://dash.plotly.com/urls#meta-tags

For more info, please see the Dash Documentation: https://dash.plotly.com/urls#nested-pages This app demonstrates the case where you have nested folders with pages folder, like in the following:

- app.py 
- pages
    - chapter1       
       |-- page1.py
       |-- page2.py
    - chapter2       
       |-- page1.py
       |-- page2.py
    - home.py

It also demos how to add arbitrary data to the page_registry. It adds icons to the page_registry which are used when creating the links.

This app uses dash-mantine-components and dash-iconify libraries. nested_folders


This app demonstrates passing variables to a page using query strings. For more information see the Dash Documentation: https://dash.plotly.com/urls#query-strings. You will also see how to use a dcc.Link within a dcc.Markdown

query_strings


This app shows how to share data between callbacks on different pages using a dcc.Store component.

share_data_between_pages



This app uses links in a table to navigate to a different page. It shows two tables:

  • The dash.DataTable has links formatted using Markdown.
  • The html table uses dcc.Link. The advantage of the html table is dcc.Link allow for the navigation to a new page without refreshing the page. The table is created with the dbc.Table.from_dataframe function from the dash-bootstrap-components library.

table_links


These examples show how to synchronize component values between pages.

You will find two example:

  1. multi_page_sync_components/ is a simple example which uses the same component on each page and sets persistence=True Thanks @nopria for the example!
  2. multi_page_sync_components2/In some cases, the simple example won't work (ie component values updated in callbacks). Version 2 uses MultiplexerTransform from the dash-extensions library to update a dcc.Store component from multiple callbacks.

sync

This example demonstrate a light and dark theme switch component from the dash-bootstrap-templates library. See a live demo at Dash Bootstrap Theme Explorer The Theme Explorer app is also made with pages ๐ŸŽ‰

For Dash Enterprise Customers, see: Dash Design Kit

theme_switch


Navigation in a callback

With Dash Pages, the routing callback is under-the-hood, which reduces the amount of boilderplate code you need to write. The best way to navigate is to use components such as the dcc.Link or dbc.Button. When the user clicks on these links, it will navigate to the new page without refreshing the page, making the navigation very fast. And the best part? No callback required! ๐ŸŽ‰

This works well when you have predefined links. However, at times, you may want to navigate based on an input field, dropdown, or clicking on a figure etc. In these cases, you should update a link dynamically in a callback. While it's possible to update the href prop of a dcc.Location in a callback, this is not recommended because it refreshes the page. You can see it in this example:

Don't do it like this! See this example -- and how to fix this when you run #15 multi_page_update_url_in_callback/ update_url_in_callback

In this example, we update the links based on the user clicking on the map. When the user clicks on the links, it navigates to the new page without refresing the page. See #16 multi_page_update_url_from_figure/

fight-status



Tips and Tricks

1. print_registry() from dash-labs>-1.1.0

When debugging a pages app, it's very helpful to inspect the content of the dash.page_registry.

print_registry() is a handy utility that pretty-prints all or part of the dash.page_registry dict.

Examples for print_registry()



from dash import Dash, html, register_page

# must use dash-labs>=1.1.0
from dash_labs import print_registry

app = Dash(__name__, use_pages=True)

register_page("another_home", layout=html.Div("We're home!"), path="/")

print_registry()

.... rest of your app

Will print to the console:

{'another_home': {'module': 'another_home',
                  'supplied_path': '/',
                  'path_template': None,
                  'path': '/',
                  'supplied_name': None,
                  'name': 'Another home',
                  'supplied_title': None,
                  'title': 'Another home',
                  'description': '',
                  'order': 0,
                  'supplied_order': None,
                  'supplied_layout': Div("We're home!"),
                  'image': None,
                  'supplied_image': None,
                  'image_url': None,
                  'redirect_from': None,
                  'layout': Div("We're home!")}}

Reference

print_registry(modules='ALL', exclude=None, include='ALL')

Params:

  • module: (string or list) Default "ALL". Specifies which modules to print.
  • exclude: (string or list) Default None. Specifies which of the page's parameter(s) to exclude.
  • include: (string or list) Default "ALL". Prints only the parameters that are specified.

Examples:

  • print_registry() Will print the entire content of dash.page_registry. If called from a file in the pages folder dash.page_registry may not be complete.
  • print_registry("pages.home") will print only one module, in this case, the pages.home module
  • print_registry(__name__) will print the current module. When called from app.py it will print all modules.
  • print_registry(["pages.home", "pages.archive"]) Will print the modules in the list.
  • print_registry(exclude="layout") will print info for all the modules, but will exclude the "layout" attribute
  • print_registry(include=["path", "name"] will print only the "path" and "name" attributes for all modules
  • print_registry(include=None) prints the keys (module names) only

2. ๐ŸŽ‰ Use dcc.Link in dcc.Markdown

Did you know it's possible to use dcc.Link in dcc.Markdown? The advantage of using dcc.Link to navigate between pages of a multi-page app is that when you click on the link it updates the pathname without refreshing the page -- which makes browsing really fast. ๐Ÿš€

Here's how:

dcc.Markdown( "This is text <dccLink href='page1/news' children='Page 1' /> more text", dangerously_allow_html=True)

For comparison, here is a regular Markdown link syntax:

dcc.Markdown( "This is text [Page 1](/page1/news) more text")

See multi_page_query_strings/ for an example. For more examples including how to format the link title with Markdown syntax or use an image get the gist.

3. Avoiding duplicate ids

All ids in the entire app must be unique, otherwise callbacks may not fire. Here are some tips to ensure that all ids in the app are unique:

3a. From this forum post as recommended by @chriddyp:

What Iโ€™ve done in big projects is to create an id function that creates the prefix automatically. This is easier with pages as each component tree is in its own layout so you can use __name__ as the prefix.

So youโ€™d write something like:

utils.py

def id(name, localid):
    return f"{name.replace('_', '-').replace('.py', '').replace('/', '')}-{localid}"

pages/historical_analysis.py

from utils import id

layout = html.Div(id=id(__name__, 'parent-div'))

3b. From this video by arjancodes

Define ids in module. It makes them easier to access, maintain, and reduces typos. See this used in multi_page_long_callback

for example:

ids.py

PAGE1_BUTTON = "page1-button"
PAGE1_GRAPH = "page1-graph"

page1.py

import ids

html.Button("button", id=ids.PAGE1_BUTTON)
dcc.Graph(ids.PAGE1.GRAPH)

@callback(
    Output(ids.PAGE1_GRAPH, "figure"),
    Input(ids.PAGE1_BUTTON, "n_clicks")
)

4. Display loading screen when page_container is loading

Shows how to make the overall loading screen only display when there is a change to the _pages_content that involves a layout being changed and not changes within the layout. See the post on the Dash Community Forum. Thanks @BSd3v for this example!

dash-multi-page-app-demos's People

Contributors

annmariew avatar ann-marie-ward avatar schwabts avatar ankitaeclipse avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.