Roadblock going from FAB to Pages

A few years back we built an internal corporate site using Flask AppBuilder (FAB) and hosting various Dash dashboards in it using iframe. We’re now refreshing the site and decided to try remove FAB and try go all-in on Dash Pages and dash-auth with OIDC, mostly due to iframe ugliness and waning FAB support. Our hope was to keep code changes to a minimum within the pages and dashboards themselves even if the ‘wrapper’ changed a lot.

We easily switched our jinja2 pages to be Dash Pages using dcc.Markdown to show the rendered templates, but ironically we’ve hit a wall with converting the hosted Dash pages. I had assumed that each Page would work like our hosted Dash instances, with each layout being dynamically loaded when the Page was changed, but it appears Dash actually builds all Page layouts at initial load and just switches which one is displayed.

This causes us issues as we duplicate a lot of standard elements across the dashboards using shared utility methods, such as office-dropdown or org-unit-table. With all the layouts now in one Dash instance, the duplication of ID’s causes callback errors for duplicate Output targets that must be renamed, or when used as Input or State don’t raise errors but cause inconsistent or broken behaviour. It appears I need to rename every element on every layout to have a fully unique ID, which then cascades to renaming the callback method parameters, etc etc. It’s rather more change than I would like, especially as it will cause a lot of ugly or duplicated code where we used to just have simple shared methods. I can’t see a way around though, unless I am missing something?

The other option would be to keep using a Flask wrapper to control routing to each individual Dash, but with all the page layout including ‘chrome’ being rendered by each individual Dash. However, I’m only aware of the Enterprise Middleware for doing this without iframe, unless there’s another way?

John.

Hi @jlayt

Dash Pages is essentially a single page app that serves different layouts based on the URL. So yes, one of the challenges is managing ids.

The dash-multi-page-app-demos repo has a helpful section on avoiding ID collisions.

It’s also possible to reuse components with the same ID across pages. This is useful if you want to sync their values across pages. Here’s an example app that demonstrates this.

You can also reuse layout components like a navbar across multiple pages — see this example where a shared component is imported and used in several layouts.

Since you are now using a newer version of dash, you can also leverage duplicate callback outputs

If you decide Dash Pages isn’t the right fit and would prefer to keep separate apps per route, the simplest option is Dash Enterprise. But if that’s not an option for you, then you could try using Werkzeug’s DispatcherMiddleware to mount multiple Dash apps under different paths.

1 Like

Thanks @AnnMarieW, that’s very useful. I’ll have a look later in the week to see if any of those works for us, as I really like the simplicity of Pages. We’re small-ish charity with zero budget, so Enterprise is not an option!

One concern is how well does Pages scale? We have about 15 dashboards already with more planned, I’m concerned at the initial start-up time for loading all the layouts in a single Dash.

Syncing values across pages may come in handy for some of our dashboards, but one concern I have is if say I reuse the office-dropdown ID across multiple pages, won’t changing the office on one page then trigger callbacks on all the pages? That could be computationally expensive. Or do only the current page callbacks trigger?

Thanks again!

John.

Hello @jlayt,

One page is available in the layout at a time, the browser only sees the individual layout, so there would only be the one callback available.

However, reusing the same id to trigger for all pages could cause other issues with missing inputs for callbacks to run, etc.

You could potentially us pattern matching ids to help with the ids so that you don’t need to come up with unique ids all the time.

You might be able to use some AI to perform this change for you.

As far as scaling goes - Dash multi-page apps scale well. A good example is the Dash documentation site, which is a large multi-page Dash app. It doesn’t use the newer Pages feature since it was built before that existed, but it shows that Dash can handle large apps with many pages without issues.

The Pages feature doesn’t change how Dash performs — it just makes it easier to build and organize multi-page apps by handling routing and layout registration for you.

For an example that uses Pages, check out dash-mantine-components.com site

One option would be to prefix the IDs (with something like the page name or so). You can use dash-extensions to streamline the process,

With this approach the amount of changes needed should be minimal (a few lines per page).

1 Like

Thanks @Emil that may well save a lot of effort, thanks!

1 Like