Search code examples
rshinyshiny-reactivityobservers

How to send reactive values into global environment for testing purposes?


I'm trying to track the flow of variables in a Shiny App by sending them into the global environment. I do this when testing to make sure outputs makes sense, understand the flows of data/variables, run further calculations, etc., and I then delete this send-to-global piece when I'm satisfied the App works fine. In this case, using rhandsontable, I'm having trouble getting this send-to-global working. I'd like to export the values of the table reflecting the user's last inputs, or if no user inputs, the table's values.

Any recommendations for how to do this? I commented-out below my usual approach, which isn't working in the example.

As an aside, is there a package or another way to dissect the way an App processes, slowly and step by step?

Code:

library(rhandsontable)
library(shiny)

rowNames1 <- c("A", "B", "C", "Sum")
data1 <- data.frame(row.names = rowNames1, "Col 1" = c(1, 1, 0, 2), check.names = FALSE)

ui <- fluidPage(
  rHandsontableOutput("hottable1"),       
  tags$div(id = "placeholder")          
)

server <- function(input, output) {
  uiTbl1 <- reactiveValues(base = data1)
  
  observeEvent(input$hottable1, {
    uiTbl1$base <- hot_to_r(input$hottable1)
  })
  
  output$hottable1 <- renderRHandsontable({
    rhandsontable(uiTbl1$base, rowHeaderWidth = 100, useTypes = TRUE)
  })
  
  observe({
    req(input$hottable1)
    DF <- hot_to_r(input$hottable1)
    DF[setdiff(rowNames1, "Sum"), ]
    DF["Sum", ] <- colSums(DF[setdiff(rowNames1, "Sum"), , drop = FALSE], na.rm = TRUE)
    uiTbl1$base <- DF
  })
  
  # uiTbl1.R <<- uiTbl1
  
  # oe1 <- reactive({req(input$hottable1)
  #   uiTbl1()})
  # observeEvent(oe1(),{uiTbl1.R <<- oe1()})
  
}

shinyApp(ui, server)

Solution

  • If you just want to check on the input values of the rhandsometable then we could use an observeEvent() and assign() the input values to the global environment. To check that its working:

    1. Change some values in the table.
    2. Close the app.
    3. Look at the test object in your global environment.
    library(rhandsontable)
    library(shiny)
    
    rowNames1 <- c("A", "B", "C", "Sum")
    data1 <- data.frame(row.names = rowNames1, "Col 1" = c(1, 1, 0, 2), check.names = FALSE)
    
    ui <- fluidPage(
      rHandsontableOutput("hottable1"),       
      tags$div(id = "placeholder")          
    )
    
    server <- function(input, output) {
      uiTbl1 <- reactiveValues(base = data1)
      
      observeEvent(input$hottable1, {
        uiTbl1$base <- hot_to_r(input$hottable1)
      })
      
      output$hottable1 <- renderRHandsontable({
        rhandsontable(uiTbl1$base, rowHeaderWidth = 100, useTypes = TRUE)
      })
      
      observe({
        req(input$hottable1)
        DF <- hot_to_r(input$hottable1)
        DF[setdiff(rowNames1, "Sum"), ]
        DF["Sum", ] <- colSums(DF[setdiff(rowNames1, "Sum"), , drop = FALSE], na.rm = TRUE)
        uiTbl1$base <- DF
      })
      
      observeEvent(uiTbl1$base, {
        assign("test", uiTbl1$base, envir = globalenv())
      })
      
    }
    
    shinyApp(ui, server)
    

    If you are interested in all subelements of uiTbl1 then you can use reactiveValuesToList(uiTbl1) wrapped in isolate() within the observeEvent():

      observeEvent(uiTbl1, {
        assign("test", isolate(reactiveValuesToList(uiTbl1)), envir = globalenv())
    

    })