What is happening to me is probably very similar to this Clientside Callback Cannot read properties of undefined - #10 by nikok.
I am using dash and manitine components to create a website. To keep control over packages and running the website I am using poetry
. The website should have a clientside_callback for when clicking a button (with any kind of action like alert
or console.log()
to see that it works). I wanted to use ClientsideFunction
to register the callback.
When implementing the callback using ClientsideFunction
and running the website with poetry run -m website
I get the error
TypeError: Cannot read properties of undefined (reading 'showAlert')
at _callee2$ (callbacks.ts:160:40)
at tryCatch (callbacks.ts:2:1)
at Generator.<anonymous> (callbacks.ts:2:1)
at Generator.next (callbacks.ts:2:1)
at asyncGeneratorStep (callbacks.ts:2:1)
at _next (callbacks.ts:2:1)
at callbacks.ts:2:1
at new Promise (<anonymous>)
at callbacks.ts:2:1
at _handleClientside (callbacks.ts:209:2)
showAlert
is defined like this in /assets/js/callbacks.js
.
window.dash_clientside = Object.assign({}, window.dash_clientside, {
clientside: {
showAlert: function(n_clicks) {
console.log("this worked!");
return '';
}
}
});
In callbacks.py
I have defined namespace
and function_name
that should be present in a js
file (which is /assets/js/callbacks.js
).
from dash import dash, Output, State, Input, callback_context, clientside_callback, ClientsideFunction
def get_callbacks(app):
app.clientside_callback(
ClientsideFunction(
namespace="clientside", # Namespace in the JavaScript file
function_name="showAlert" # Function name defined in the JavaScript file
),
Output('connection_status', 'color'),
Input('vnc_connect', 'n_clicks')
)
This is __main__.py
where the server gets the layout and callbacks.
import dash_mantine_components as dmc
from dash import Dash, _dash_renderer, html, Input, Output, callback, State
from website.layout import get_layout
from website.callbacks import get_callbacks
_dash_renderer._set_react_version("18.2.0")
app = Dash(assets_ignore=r"(?!callbacks\.js).*") # I only want this file to run
app.layout = get_layout()
get_callbacks(app)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True, port="8000")
This is layout.py
with three simple components from mantine
.
import dash_mantine_components as dmc
from dash import html
def get_layout():
return dmc.MantineProvider(
[
dmc.Container([
dmc.Badge("Disconnected", variant="dot", color="yellow", id="connection_status"),
dmc.Button("Connect to Server", id="vnc_connect", w=200),
dmc.PasswordInput(label="Server Password", w=200, id="server_password",placeholder="Server password", required=True),
])
]
)
This is my current directory structure
├── poetry.lock
├── pyproject.toml
└── website
├── __init__.py
├── __main__.py
├── assets
│ └── js
│ └── callbacks.js
├── callbacks.py
└── layout.py
The error is not always 100% persistent when reloading the page, but persistent enough to cause trouble on the client side.
My problem seems to be a bit similar to this problem. When imbeding javascript in the callback directly like this it works much better.
def get_callbacks(app):
app.clientside_callback(
"""
function(value) {
alert("asd");
}
""",
Output('connection_status', 'color'),
Input('vnc_connect', 'n_clicks')
)
But why he gets undefined
when trying to put the javascriot in a js
file instead is not answered.
After digging a bit I saw that when putting the javascript in a file and it does work it is seen here, and when it doesnt work its not seen.
Why would my required js file sometimes appear, and other times not? And how do I fix it?
For now I have began to include callbacks.js (and other js files) by using embedded javascript to put a script tag at the bottom of the html body. It works consistently if i do that.