Load Page Specific Assets in Multi-Page App

I’m putting together a multi-page app. There are common site components in the app (like the sidenav), but the main content area is page specific.

I’m trying to define the page-specific clientside callbacks in a separate JS file per page. I.e. I only want to load in the corresponding javascript file for the active page.

I’m using ClientsideFunction to load in the callbacks. So the JS file must be loaded in before the clientside_callback functions are initiated so the functions can be referenced.

This process works nicely when I put the page-specific JS files under the assets/ directory and they are loaded in automatically. Eventually my site is going to have upwards up 5 pages and I don’t want to load in all of these asset files un-necessarily.

I’m trying to exclude the files using the “assets_ignore” parameter in the Dash() constructor and later including the JS file with dash.html.Script() but I get the error:

TypeError: Cannot read properties of undefined (reading ‘apply’)

which I’m pretty sure is referring to the ClientsideFunction() call not being able to find the defined clientside callback function.

I can’t use the dash_defer_js_import library because that would be too late.

I could define all of these functions as strings into clientside_callback but I’m using utility functions defined in other JS namespaces in these callback functions so I would like to keep them defined in the external files.

Any ideas how to implement this?

Let me know if more information is needed.

1 Like

Hello @dt_sweeper,

You could utilize the underlying flask templates to do this.

Have a clientside callback that listens to the path whenever the url changes, then send a GET request to the same endpoint, with .js appended. This is where your Flask server would take over and return your js file.

page registered = home
js functions = home.js

@app.server.route('/home.js'):
def homeJS():
    return flask.render_template('home.js')

You should create a templates directory in the same manner that you create an assets folder.

Alternatively, you could do something like this:

newScript = document.createElement("script")
newScript.src = '../home.js'
document.body.append(newScript)

^ this will load the script as needed.

2 Likes