I was getting a similar error when appending javascript. The only solution I could come up with (and it’s a hack) was to force the javascript to wait using ‘setTimeout’. Might be helpful here too? See Append script when dash components are loaded
Could you please post a small, reproducable example that demonstrates the issue? Thanks
Sure, thanks for responding! A warning: I know very little about javascript.
Some context: I am developing a Dash app which will be embedded within an iframe. The Dash app needs to pass information back to the parent domain (I think that’s the term).
The code below works (I hope!) insofar as it will attempt to send a message back to the parent domain when the button is clicked. This is evident in the console log when developer tools are turned on in the browser (“Sending message to parent at () s=Alice the camel has 1 humps”). It will generate an error (“Invalid target origin ‘’ in a call to ‘postMessage’”), but that is only because there is no parent domain in this minimum example.
What I was getting at in the previous post is that this example will only work with the setTimeout function (lines 52 and 59). Without this, the console log shows an error: “Uncaught TypeError: Cannot set property ‘onclick’ of null”. Presumably because the button has not yet been defined. The button will no longer print to the console, not attempt to message the parent domain.
There is also the matter of co-opting the title of the hidden div to store the message. Not elegant.
Note: Change lines 7 and 8 to match your setup.
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import dash
from base64 import urlsafe_b64encode
app = dash.Dash(url_base_pathname="/XXX/")
PORT = 123
server = app.server
app.config.supress_callback_exceptions = True
my_jquery = "https://code.jquery.com/jquery-3.1.0.js"
app.scripts.append_script({
"external_url": my_jquery
})
def write_to_data_uri(s):
uri = (
('data:;base64,').encode('utf8') +
urlsafe_b64encode(s.encode('utf8'))
).decode("utf-8", "strict")
return uri
# Get parentDomain
# Define JS func "sendMessageToParent"
app.scripts.append_script({
'external_url': write_to_data_uri("""
var parentDomain = '';
window.addEventListener('message',function(event) {
console.log('message received from parent: ' + event.data,event);
parentDomain = event.data;
},false);
function sendMessageToParent(s) {
console.log("Sending message to parent at ("+parentDomain+") s=" + s);
parent.postMessage(s,parentDomain);
}
""")})
# Javascript to message the parent. Or, in more detail, to send the 'title' of
# the div 'msg_for_parent' to the parent domain.
app.scripts.append_script({
'external_url': write_to_data_uri("""
setTimeout(function(){
$(document).ready(function(){
document.getElementById("exec_js").onclick = function(){
var msg = document.getElementById("msg_for_parent").title;
sendMessageToParent(msg);
};
});
}, 2000);
""")})
app.layout = html.Div([
# Hidden div to store the message/string which will be sent to the parent
# domain using 'title' to store the message/string because it is easy to get
# javascript funciton to retrieve the value of the title
html.Div(
id='msg_for_parent',
title='',
style={'display': 'none'}
),
html.Div([
dcc.Dropdown(
id='how_many_humps',
options=[{'label': i, 'value': i} for i in range(5)],
value=1,
)
],),
# Button to execute javascript. Does nothing in the dash world
html.Button(
'Click Me',
id='exec_js',
),
])
@app.callback(
dash.dependencies.Output('msg_for_parent', 'title'),
[dash.dependencies.Input('how_many_humps', 'value')]
)
def update_msg_for_parent(value):
msg = "Alice the camel has %s humps" % value
return msg
if __name__ == '__main__':
app.run_server(debug=True, port=PORT)
Oh I see, this is actually unrelated to the Dash DataTable, this is related to adding custom JS. I’m going to move this to a new issue.
hi, you can try visdcc.Run_js, it allows you run javascript in callback
Same issue here. I checked that the JavaScript files in the assets folder won’t be able to get the document, i.e. “document” will return you null.
I tried async, defer, or force the script to be after the renderer stuff. None of them worked.
My guess is the app entry was rendered after the scripts had run. Since dash front end is actually ReactJS, it won’t be easy to get DOM items. Also, Dash doesn’t support ReactJS refs yet, I guess currently the only way is to modify the renderer and put everything there post rendering…