Search code examples
rshinyshiny-server

Dynamic Input Selector Based on Uploaded Data


Thanks in advance for your help. I understand how to manipulate dynamic inputs based off of other inputs for pre-defined datasets. i.e. Load a car dataset. User selects Radio button to say they only want to look at blue cars. This changes the options in some Input Selector on the UI.

However, if I want to allow a user to upload a csv file, how do I dynamically update all of the relevant widgets. i.e. User uploads their data, an Input Selector displays all variables in the dataset for plots and regressions.

The italicized part is my trouble.

ui.r

library(shiny)

# Define UI for application that draws a histogram
shinyUI(fluidPage(

  titlePanel("My R Shiny App"),

  sidebarPanel(
    fileInput('file', 'Choose file to upload.'),
    #Select Box: y
    selectInput("y_input", label = h5("Select Time Series/Response Variable"),
                choices = names(myData),
                selected = NULL)

  )
) 
)

server.r

library(shiny)

#Run once when app is launched
#Load data

shinyServer(function(input, output) {

  #Run once each time a user visits the app
  #Put code to build a distinct set of reactive objects for user


  output$Variable_Selector <- renderUI({
    if(is.null(input$file))
      return(NULL)
    inFile <- input$file
    myData <- read.csv(inFile$datapath)
    if (is.null(myData))
      return(NULL)
  })
})

global.r

myData = NULL

Thanks!


Solution

  • Here's one solution using the functions observe and updateSelectInput - with some other minor modifications to your code. To demonstrate I made the following two csv files with different column names:

    Df1 <- data.frame(
      x=1:5,
      y=2*(1:5),
      z=3*(1:5))
    ##
    Df2 <- data.frame(
      a=6:10,
      b=2*(6:10),
      c=3*(6:10),
      d=letters[1:5],
      stringsAsFactors=F)
    ##
    write.csv(Df1,file="~/tempfiles/Df1.csv",row.names=F)
    ##
    write.csv(Df2,file="~/tempfiles/Df2.csv",row.names=F)
    

    ui.R:

    library(shiny)
    
    shinyUI(fluidPage(
    
      titlePanel("My R Shiny App"),
    
      sidebarPanel(
    
        fileInput(
          'file', 
          'Choose file to upload.'
        ),
    
        selectInput(
          "y_input", 
          label = h5("Select Time Series/Response Variable"),
          ""
        )
    
      )
    
    ))
    

    server.R:

    library(shiny)
    
    shinyServer(function(input, output, session) {
    
      inFile <- reactive({
        if (is.null(input$file)) {
          return(NULL)
        } else {
          input$file
        }
      })
    
      myData <- reactive({
        if (is.null(inFile())) {
          return(NULL)
        } else {
          read.csv(inFile()$datapath)
        }
      })
    
      observe({
        updateSelectInput(
          session,
          "y_input",
          choices=names(myData()))
    
      })
    
    })
    

    global.R:

    myData <- NULL
    

    And here are a couple of screenshots showing how the UI changes based on the uploaded file:

    Uploading <code>Df1.csv</code>

    Uploading <code>Df2.csv</code>