Search code examples
rshinydatabricksreactive

Cannot paste network path to list files


i've built an app that allow users to paste a folder path so that files inside that folder can be listed and selected. The app works when i set the path globally but i really need users to be able to stipulate their path. The path needs to be a network path as we use Azure/Databricks...

library(dplyr)
library(shinyWidgets)
library(shinythemes)
library(DT)

fpath <- '/dbfs/dbfs/Analytics/ShinyApp' #example path

# Define UI
ui <- fluidPage(
  theme = shinytheme("spacelab"),
  navbarPage(
    "App",
    tabPanel(
      "Setup Project",
      sidebarPanel(
        textInput("v_inpath", "Specify File Path:", ""),
        actionButton("Setpath", "Set Path"),
        selectInput("selectfile", "Select File to Analyse",choice = list.files("ppath", pattern = ".csv")) #list of files should show up here
      ), # sidebarPanel
      mainPanel(verbatimTextOutput("ppath")) # mainPanel
    ) #tabPanel
  ) # navbarPage
) # fluidPage

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

  observeEvent(input$Setpath,{
  output$ppath <-reactive({paste0(input$v_inpath)})
})  
} # server

# Create Shiny object
shinyApp(ui = ui, server = server)

In the mainPanel, i can see the path being pasted correctly as text (as you can see i'm using verbatimTextOutput("ppath")). The list of files contained in the specified folder should show up but it does not work as no list is available... Thank you in advance for your help


Solution

    • You need renderUI

    • You should avoid to put an output element inside an observer

    • You could use the shinyFiles package or the jsTreeR package to select the path

    Code:

    library(shiny)
        
    # Define UI
    ui <- fluidPage(
      navbarPage(
        "App",
        tabPanel(
          "Setup Project",
          sidebarPanel(
            textInput("v_inpath", "Specify File Path:", ""),
            actionButton("Setpath", "Set Path"),
            uiOutput("selectfileUI")
          ), # sidebarPanel
          mainPanel(verbatimTextOutput("ppath")) # mainPanel
        ) #tabPanel
      ) # navbarPage
    ) # fluidPage
    
    # Define server function
    server <- function(input, output, session) {
      
      output[["selectfileUI"]] <- renderUI({
        req(input[["Setpath"]])
        files <- list.files(input[["v_inpath"]], pattern = ".csv")
        selectInput("selectfile", "Select File to Analyse", choices = files)
      })
      
      output[["ppath"]] <- renderPrint({
        input[["v_inpath"]]
      })
      
    } # server
    
    # Create Shiny object
    shinyApp(ui = ui, server = server)
    

    EDIT: feedback

    Also, you can use the shinyFeedback package to print a message when the path is not valid:

    library(shiny)
    library(shinyFeedback)
        
    # Define UI
    ui <- fluidPage(
      useShinyFeedback(), # don't forget this line
      navbarPage(
        "App",
        tabPanel(
          "Setup Project",
          sidebarPanel(
            textInput("v_inpath", "Specify File Path:", ""),
            actionButton("Setpath", "Set Path"),
            uiOutput("selectfileUI")
          ), # sidebarPanel
          mainPanel(verbatimTextOutput("ppath")) # mainPanel
        ) #tabPanel
      ) # navbarPage
    ) # fluidPage
    
    # Define server function
    server <- function(input, output, session) {
      
      Check <- eventReactive(input[["Setpath"]], {
        dir.exists(input[["v_inpath"]])
      })
      
      Files <- reactive({
        req(Check())
        list.files(input[["v_inpath"]], pattern = ".csv")
      })
      
      
      observeEvent(input[["Setpath"]], {
        hideFeedback("v_inpath")
        show <- !Check() || length(Files()) == 0
        if(show) {
          if(Check()) {
            text <- "No CSV file in this folder"
          } else {
            text <- "Invalid path"
          }
          showFeedbackWarning("v_inpath", text)
        } else {
          hideFeedback("v_inpath")
        }
      })
      
      output[["selectfileUI"]] <- renderUI({
        req(Files())
        selectInput("selectfile", "Select File to Analyse", choices = Files())
      })
      
      output[["ppath"]] <- renderPrint({
        input[["v_inpath"]]
      })
      
    } # server
    
    # Create Shiny object
    shinyApp(ui = ui, server = server)