plotly / dash-labs

Work-in-progress technical previews of potential future Dash features.
MIT License
139 stars 39 forks source link

Multi Page Apps: Issue with Dynamic Layouts #81

Closed bigmike36c closed 2 years ago

bigmike36c commented 2 years ago

I'm having an issue using dynamic layouts with dash lab's pages/ plugin. I'm trying to use a dynamic layout to fetch new data when the user refreshes the page as detailed in the docs. However, I keep receiving the error message shown below.

Screen Shot 2022-01-27 at 11 48 50 PM

The only way I can get around this error is setting app.layout equal to the function call, "serve_layout()", instead of the function instance, "serve_layout". I don't understand why my "fix" worked, and from what I can tell in my testing, the layout is no longer dynamic and does not respond to changes in the data source when I refresh the page. I've included a simple example that just requires an empty pages/ directory in addition to the code below.

from dash import Dash, html, dcc
import dash
import dash_labs as dl

app = Dash(__name__, plugins=[dl.plugins.pages])

dash.register_page("another_home", layout="We're home!", path="/")
dash.register_page(
    "very_important", layout="Don't miss it!", path="/important", order=0
)

def serve_layout():
    return html.Div(
    [
        html.H1("App Frame"),
        html.Div(
            [
                html.Div(
                    dcc.Link(f"{page['name']} - {page['path']}", href=page["path"])
                )
                for page in dash.page_registry.values()
                if page["module"] != "pages.not_found_404"
            ]
        ),
        dl.plugins.page_container,
    ]
)

app.layout = serve_layout

if __name__ == "__main__":
    app.run_server(debug=True)
michaelbabyn commented 2 years ago

the error seems to be coming from the validation layout which doesn't check to see whether the app.layout is a function https://github.com/plotly/dash-labs/blob/fa90c6f9dd1445cfed6ca799ad3965a6b5ffd910/dash_labs/plugins/pages.py#L378

changing that line to [app.layout() if callable(app.layout) else app.layout] resolves the issue for me

AnnMarieW commented 2 years ago

Thanks @michaelbabyn !! Would you like to do the PR for your solution, or would you prefer I add it to the one I have open now?

michaelbabyn commented 2 years ago

Sorry for the late response, @AnnMarieW please add it to yours since it's probably simpler that way