Pushkar
Pushkar

Reputation: 45

Read a file after taking user input(selection) in Shiny

I am trying to read a file after taking inputs from user - first a date and then a selection of file, but I can't get the code read any file and do anything with it. The Error message is following. Also is there a way to make this code more efficient?

   ui <- fluidPage(
    titlePanel("Select the execution date")
    ,dateInput("ME_DATE",label=h3("Execution Date Input"), value="2020-05-29")
    ,hr()
    ,fluidRow(column(3,verbatimTextOutput("Output_path")))
    ,hr()
    ,selectInput('selectfile','Select File in Above Location', choices=NULL)
    ,textOutput('fileselection_statement')
    ,tableOutput('selected_table')

)

server <- function(input, output, session) {
    # Location for Outputs
    Output_DIR <- "K:/Outputs/"
    Output_loc <- reactive({
                                    
    year_N_ME_DATE <- format(input$ME_DATE,"%Y")
    month_N_ME_DATE <- format(input$ME_DATE,"%m")
    month_T_ME_DATE <- months(input$ME_DATE)

    file.path(paste(Output_DIR,month_N_ME_DATE,". ",month_T_ME_DATE, " ",year_N_ME_DATE,"/",sep=""))
    })
    
    # Output Path
    output$Output_path <- renderPrint({ Output_loc() })

    # files list
    Updated_Output_files_list <- reactive({ list.files(Output_loc()) })

    observeEvent(input$selectfile, {    
    updateSelectInput(session, "selectfile", choices=Updated_Output_files_list())
    output$fileselection_statement <- renderText({paste0('You have selected: ', input$selectfile) })

    })
    selectfile <- reactive(get(input$selectfile))
    output$selected_table <- renderTable({  read.csv(paste0(renderPrint({ Output_loc() }),renderPrint({ selectfile() }),sep="")) }) 
}

shinyApp(ui, server)

Upvotes: 0

Views: 818

Answers (1)

r2evans
r2evans

Reputation: 161065

  1. (Since changed) Make the block containing file.path(.) a reactive block and assign it to something so that other reactive components can use it. In your case, you changed it to Output_loc, so other blocks will refer to it as Output_loc().

  2. Similarly, you cannot put output$... <- assignments or render* calls inside an observe or observeEvent block. So we'll move your output$fileselection_statement outside of the observeEvent.

  3. renderPrint is its own rendering function, on the same level as renderTable. You cannot nest them. In this case, I'm just going to remove them from inside the renderTable call, they make no sense there.

  4. This case did not need selectfile <- reactive(get(input$selectfile)), there is no apparent gain in that indirection. Just use input$selectfile. Removed.

  5. After fixing all of the above, it is also the case that you were updating the selectInput every time the selectInput was changed, which is incorrect (and completely disallows any real use of this). Instead, you want to update it when the Updated_Output_files_list() changes.

  6. Also, instead of repeatedly concatenating the path together to create the file to be read, I use list.files(..., full.names=TRUE). This will be a named vector, where the values are the full path and filename, but the names will be just the filename (no leading path). This useful because selectInput displays the name but returns the value (full path). There is rarely a time when I think not specifying full.names=TRUE is the right thing (I cannot think of any right now).

Here's a working copy. It is not perfectly-awesome, there are still areas where some grooming might be in order.

server <- function(input, output, session) {
  # Location for Outputs
  Output_DIR <- "K:/Outputs/"
  Output_loc <- reactive({
    year_N_ME_DATE <- format(input$ME_DATE, "%Y")
    month_N_ME_DATE <- format(input$ME_DATE, "%m")
    month_T_ME_DATE <- months(input$ME_DATE)
    file.path(Output_DIR,
              paste0(month_N_ME_DATE, ". ", month_T_ME_DATE, " ", year_N_ME_DATE),
              "/")
  })
  # alternative
  # Output_loc <- reactive({
  #   file.path(Output_DIR, format(Sys.Date(), format = "%m. %b %Y"))
  # })
  
  # Output Path
  output$Output_path <- renderPrint({ req(Output_loc()) })

  # files list
  Updated_Output_files_list <- reactive({
    lf <- list.files(Output_loc(), full.names = TRUE)
    names(lf) <- basename(lf)
    # in this example, 'lf' is now:
    # c(iris.csv = "K:/Outputs/05. May 2020/iris.csv", mtcars.csv = "K:/Outputs/05. May 2020/mtcars.csv")
    # ... the *name* will be displayed in the selectInput, but the
    # *full path* will be the value of the selection
    lf
  })

  output$fileselection_statement <- renderText({
    paste0('You have selected: ', input$selectfile)
  })

  observeEvent(Updated_Output_files_list(), {
    updateSelectInput(session, "selectfile", choices = Updated_Output_files_list())
  })

  output$selected_table <- renderTable({
    req(input$selectfile)
    read.csv(input$selectfile)
  }) 
}

Upvotes: 1

Related Questions