shiny
shiny copied to clipboard
Feature request: javascript variable to check if the server has been connected yet
We have the shiny:connected
JavaScript event that triggers when there's a connection with the server, and that's useful in many contexts.
However, sometimes you may want to run JavaScript code (in my case, Shiny.setInputValue()
) on demand, but you don't know if the server has been connected yet or not.
Right now, my approach is:
if (typeof Shiny === "undefined" || typeof Shiny.setInputValue === "undefined") {
$(document).on('shiny:connected', function(event) {
Shiny.setInputValue("foo", "bar");
});
} else {
Shiny.setInputValue("foo", "bar");
}
It seems that a Shiny
javascript object does exist initially but it doesn't yet hae setInputValue
, so this works, but feels very wrong. It's also not guaranteed to keep working since it's undocumented. It would be great to know if there's a better solution, or if perhaps adding a Shiny.connected
variable which initializes to false
would be good.
@daattali : Is your issue related to what I have noticed in the issue below ?
In others terms it's sometime difficult to know when we could load Javascript for some specific cases, except to use tweaks.
- https://github.com/rstudio/shiny/issues/2676
@daattali there's the Shiny.shinyapp.isConnected()
function ... does that work for your use case?
Either way, I also struggle with this, e.g. when trying to send a message to the server on specific events, like shiny:bound
(so I can safely defer any sendInputMessage()
s from the server to that input element). Adding something like this to a custom input binding's initialize()
method:
initialize: function(el) {
$(el).one("shiny:bound", function(event) {
Shiny.setInputValue("input_name", "some_signal");
}
... in theory registers an event handler to notify the server when the input is bound, but this fails for statically-loaded inputs on app startup since the shiny:bound
event occurs prior to the connection being established (and Shiny.setInputValue()
fails).
One could be slightly more robust with a conditionally-deferred handler like:
initialize: function(el) {
$(el).one("shiny:bound", function(event) {
if (Shiny.shinyapp.isConnected()) {
Shiny.setInputValue("input_name", "some_signal");
} else {
$(document).one("shiny:connected", function(event) {
Shiny.setInputValue("input_name", "some_signal");
});
}
});
}
... but this feels pretty hacky.
What'd be neat is if Shiny.setInputValue()
could (i) exist prior to any other Shiny events firing and (ii) FIFO queue any messages until the connection is fully established then fire them off.
+1 from me. My current workaround is this helper (since Shiny.shinyapp
is also undefined at first):
function setShinyInput(name, value) {
if (Shiny.shinyapp?.isConnected()) {
Shiny.setInputValue(name, value);
} else {
$(document).one("shiny:connected", () => setShinyInput(name, value));
}
};