pedrosaurio
pedrosaurio

Reputation: 4926

How to modify a js variable within a shiny server (htmlwidgets/R)

This question is more conceptual than explicit to a particular piece of code so I guess there's no toy-code this time.

I have a rather large shiny app that uses some d3.js scripts. The D3 objects access a few global variables when their update functions are called. I'd like to control these variables from the Shiny server - is this possible?

Upvotes: 1

Views: 715

Answers (1)

Ryan Morton
Ryan Morton

Reputation: 2695

This app assumes the global variable was assigned to the window. Then it uses a custom message handler to create the original variable (#1) and another to manipulate the value of that variable (#2).

Edited to have message sent back to R with the state of the global variable.

R Code:

library(shiny)

ui <- fluidPage(

# Application title
titlePanel("Global Variable Manipulation"),

  mainPanel(
    sliderInput("data", "Element", min = 0, max = 100, value = 0),
    actionButton("go", "GO"),
    textOutput("var"),
    singleton(
      tags$head(tags$script(src = "message-handler.js"))
    ),
    singleton(
      tags$head(tags$script(src = "message-handler2.js"))
    ),
    singleton(
      tags$head(tags$script(src = "back-to-shiny.js"))
    )
  )

)


server <- function(input, output, session) {

  observe({
    session$sendCustomMessage(type = 'testmessage',
                              message = list(a = 1, b = 'text',
                                             controller = input$data))
  })

  observeEvent(input$go,{
    session$sendCustomMessage(type = 'changeMessage',
                              message = list(2))
  })

  output$var <- renderPrint({
    input$jsvalue
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

message-handler.js code:

Shiny.addCustomMessageHandler("testmessage",
  function(message) {
     window.globalVar = message.controller
    alert(JSON.stringify(window.globalVar));
  }
);

message-handler2.js code:

Shiny.addCustomMessageHandler("changeMessage",
  function(message) {
    window.globalVar = window.globalVar-message;
    alert(JSON.stringify(window.globalVar));
  }
);

back-to-shiny.js code:

setInterval(function(){
    var message = window.globalVar;   
    Shiny.onInputChange("jsvalue", message);
},0);

Upvotes: 3

Related Questions