Reputation: 12394
I am working with Shiny
and JavaScript
. I extend the functionality of Shiny
with JavaScript
. Doing that, I work with callbackHandlers.
I observe the userinput with a click event
implemented in JS
. Once the event is fired, I send the needed data to R
, where a function works with the data. The results again get send back to JS
where the display of the data handled.
So. on my JS
side I have something like this:
for(var i = 0; i < radioButtons.length; i++) {
radioButtons[i].onclick = function() {
if (parseInt(this.value) === 10) {
Shiny.onInputChange("go", this.value);
Shiny.addCustomMessageHandler("someCallbackHandler1", function(someJson) {
someFunction(someJson);
});
} else if (parseInt(this.value) === 11) {
Shiny.onInputChange("go", this.value);
Shiny.addCustomMessageHandler("someCallbackHandler2", function(someJson) {
someFunction(someJson);
});
} // more else if checking for the value
....
On the R
side I do this
observe({
if( !is.null(input$go) ) {
if( (input$go == 10) ) {
sendToJs1[["myJson"]] <- someFunctionIwrote(arg1, arg2, arg3, arg4)
session$sendCustomMessage(type = "someCallbackHandler1", sendToJs1$myJson)
} else if( (input$go == 11) ) {
sendToJs2[["myJson"]] <- someFunctionIwrote(arg1, arg2, arg3, arg4, arg5, arg6)
session$sendCustomMessage(type = "someCallbackHandler2", sendToJs2$myJson)
} # more else if checking for which value gets send from js
....
When I click on the radioButton
with the value 10
, then on the radioButton
with the value 11
and then again on the radioButton
with the value 10
I get this.
Uncaught handler for message of type “ someCallbackHandler1” already added
So JS
notices that the callbackHandler1
is already added and does not add it again. But I need it to be added again in order to display the data. Further, what would JS
do if the input data changes and someFunctionIwrote(arg1, arg2, arg3, arg4)
is executed with different input data? Of course the callbackHandler1
is already added, but whats inside, the results send from R
to JS
is different.
How would I manage this situation?
Upvotes: 0
Views: 53
Reputation: 1723
My recommendation would be:
Define your javascript event handlers only once, and outside your loops. No need to define them more than once. They will continuously listen to the messages from the server once they have been created.
Make sure that the callback functions stated in the handlers are flexible enough to handle all your server responses. So your function someFunction()
should be able to handle all possible messages from the server.
So the code would be:
// function to be called from inside the callback functions:
function someFunction(someJson){
console.log("No matter what someJson is, I will handle them all properly!");
...
}
// set the event handlers for message from server:
Shiny.addCustomMessageHandler("someCallbackHandler1", function(someJson) {
someFunction(someJson);
});
Shiny.addCustomMessageHandler("someCallbackHandler2", function(someJson) {
someFunction(someJson);
});
// set the event handlers for radio button clicks:
for(var i = 0; i < radioButtons.length; i++) {
radioButtons[i].onclick = function() {
if (parseInt(this.value) === 10) {
Shiny.onInputChange("go", this.value);
} else if (parseInt(this.value) === 11) {
Shiny.onInputChange("go", this.value);
} // more else if checking for the value
Upvotes: 1