Search code examples
rshinyglobal-variables

Shiny: update varSelectInput() using the column names of a global variable


I have a shiny app, which reads a csv data table, and then processes the table and saves the processed data as a global variable DFG (I used <<- assignment operator to produce this global variable). This global variable will be used in another session for further data analysis.

In the new shiny session, I would like to access the column names of this global variable and use it to subset the data.

However, it did not work. It seems that the varSelectInput() cannot be updated.

When I tried with an R internal data iris, the code worked. I don't know what should I do to make it work for my global variable.

  1. It works for Iris data
library(shiny)

ui = fluidPage(
  varSelectInput(inputId = "getColumn", label="Get Column", data = ""),
  tableOutput("table")
)

server = function(input, output, session){

  StatGroup <- reactive({
    return(as.character(input$getColumn))
  })
  
  updateVarSelectInput(inputId = "getColumn",
                       data = iris,
                       selected = "")
  
  output$table <- renderTable(iris[, StatGroup(), drop = FALSE])

}

shinyApp(ui, server)

Basically what I want to do is something like this:

  1. It does not work for my global data DFG
library(shiny)

ui = fluidPage(
  varSelectInput(inputId = "getColumn", label="Get Column", data = ""),
  tableOutput("table")
)

server = function(input, output, session){

  StatGroup <- reactive({
    return(as.character(input$getColumn))
  })

if(!exists(deparse(substitute(DFG)))) {DFG <- NULL} # this one does not work

  updateVarSelectInput(inputId = "getColumn",
                       data = DFG,
                       selected = "")
  
  output$table <- renderTable(iris[, StatGroup(), drop = FALSE])

}

shinyApp(ui, server)
  1. This method works. But I don't understand why. This method is not ideal for me as I have no a prior information of user upload column names.

Suppose my DFG has two columns, named Group1 and Group2

then if I add the code DFG <- data.frame(Group1 = "", Group2 = ""), and it worked.

library(shiny)

ui = fluidPage(
  varSelectInput(inputId = "getColumn", label="Get Column", data = ""),
  tableOutput("table")
)

server = function(input, output, session){

  StatGroup <- reactive({
    return(as.character(input$getColumn))
  })

  DFG <- data.frame(Group1 = "", Group2 = "") ## with this code, it worked
  
  updateVarSelectInput(inputId = "getColumn",
                       data = DFG,
                       selected = "")
  
  output$table <- renderTable(iris[, StatGroup(), drop = FALSE])

}

shinyApp(ui, server)

Solution

  • Instead of a plain old global variable to store the data, use a global reactive value that you define up front. Then when that gets updated, other sessions using it will be notified, too.

    library(shiny)
    
    global_data <- reactiveVal(NULL)
    
    ui <- fluidPage(
      actionButton("go", "Sample a dataset"),
      varSelectInput("col", "Pick a column", NULL)
    )
    
    server <- function(input, output, session) {
      observeEvent(input$go, {
        dataset <- NULL
        while (is.null(names(dataset))) {
          dataset <- sample(ls("package:datasets"), 1)
          dataset <- get(dataset, "package:datasets")
        }
        global_data(dataset)
      })
      
      observeEvent(global_data(), {
        updateVarSelectInput(session, "col", data = global_data())
      })
    }
    
    shinyApp(ui, server)