Get the path for a folder chosen by user in shiny - r

I would like the user to be able to choose a folder (Ill retrieve the path for this later).
At the moment this works for selection of a file but not a folder. I cant explain why. And the directory does have files in it (tested on windows and mac).
Any ideas?
library(shiny)
library(shinyFiles)
ui <- fluidPage(
shinyFilesButton("Btn_GetFile", "Choose a file" ,
title = "Please select a file:", multiple = FALSE,
buttonType = "default", class = NULL),
shinyDirButton('folder', 'Folder select', 'Please select a folder', FALSE),
textOutput("txt_file")
)
server <- function(input,output,session){
volumes = getVolumes()
observe({
shinyFileChoose(input, "Btn_GetFile", roots=volumes, session = session)
if(!is.null(input$Btn_GetFile)){
# browser()
file_selected<-parseFilePaths(volumes, input$Btn_GetFile)
output$txt_file <- renderText(as.character(file_selected$datapath))
}
})
observe({
if(!is.null(input$Btn_Folder)){
# browser()
shinyDirChoose(input, 'folder', roots=volumes)
dir <- reactive(input$folder)
output$dir <- renderText(as.character(dir()))
}
})
}
shinyApp(ui = ui, server = server)

That's because you wrote Btn_Folder instead of folder here:
observe({
if(!is.null(input$Btn_Folder)){
shinyDirChoose(input, 'folder', roots=volumes)
dir <- reactive(input$folder)
output$dir <- renderText(as.character(dir()))
}
})
Replace with:
observe({
if(!is.null(input$folder)){
shinyDirChoose(input, 'folder', roots=volumes)
dir <- reactive(input$folder)
output$dir <- renderText(as.character(dir()))
}
})
As a side note, you don't need to define this reactive conductor inside the observer, simply do:
observe({
if(!is.null(input$folder)){
shinyDirChoose(input, 'folder', roots=volumes)
output$dir <- renderText(as.character(input$folder))
}
})

Related

How to select multiple folders with shinyDirButton in R

I'm trying to write a small shiny app where the user can select multiple folders through a button. The number of folders selected varies according to the needs of the user. The selection of one folder works. If I set "multiple = TRUE", then also only one folder is selected. Does anyone have an idea how I can select multiple folders with a single button?
Here is my code:
library(shiny)
library(shinydashboard)
library(shinyFiles)
library(shinyWidgets)
ui <- fluidPage(
shinyDirButton("preinfolder", "Choose a folder" ,
title = "Please select a folder:",
buttonType = "default", class = NULL,
icon = icon("folder", lib = "font-awesome"), multiple = TRUE),
textOutput("prein_txt_file")
)
server <- function(input, output, session) {
volumes = getVolumes()()
observe({
shinyDirChoose(input, "preinfolder", roots = volumes, session = session)
if(!is.null(input$preinfolder)){
# browser()
preinfolder_selected<-parseDirPath(volumes, input$preinfolder)
output$prein_txt_file <- renderText(preinfolder_selected)
}})
}
shinyApp(ui, server)
Thanks for any idea
I am still trying to solve the problem. I want a list of selected folders.
For my previous solution, I can select multiple folders but only from one parent folder.
library(shiny)
library(shinydashboard)
library(shinyFiles)
library(shinyWidgets)
ui <- fluidPage(
shinyDirButton("preinfolder", "Choose a folder" ,
title = "Please select a folder:",
buttonType = "default", class = NULL,
icon = icon("folder", lib = "font-awesome"), multiple = TRUE),
uiOutput(outputId = "sel_subfolder"),
textOutput("prein_txt_file")
)
server <- function(input, output, session){
volumes = getVolumes()()
observe({
shinyDirChoose(input, "preinfolder", roots = volumes, session = session)
if(!is.null(input$preinfolder)){
# browser()
preinfolder_selected<-parseDirPath(volumes, input$preinfolder)
output$prein_txt_file <- renderText(preinfolder_selected)
}})
df <- reactive({
if(is.null(input$preinfolder)) {
return(NULL)
} else {
fol <- parseDirPath(volumes, input$preinfolder)
return(fol)
}
})
output$sel_subfolder <- renderUI({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df())) {
return(tags$div(align = "left",
class = "multicol",
checkboxGroupInput(inputId = "sel_subfolder",
label = "Select subfolder",
choices = unlist(list.files(parseDirPath(volumes, input$preinfolder))))))
}
})
}
shinyApp(ui, server)
I am still looking for a solution how to create a list of multiple folders with one input button.
This is the solution I found (a bit convoluted but it works).
You basically pass the selected folder to a updateCheckboxGroupInput function that appends the folder to a list of previously chosen ones
library(shiny)
library(shinyFiles)
ui <- fluidPage(
titlePanel("Test"),
sidebarLayout(
sidebarPanel(
shinyDirButton('fld','Choose...','Choose a folder'),
actionButton("submitbutton", "Add folder", class = "btn btn-primary"),
checkboxGroupInput('chosenfolders','Chosen folders...')
),
mainPanel(
verbatimTextOutput("selected")
)
)
)
server <- function(input, output, session) {
volumes <- c(Home = fs::path_home(), "R Installation" = R.home(), getVolumes()())
shinyDirChoose(input, 'fld', session=session,
root=volumes, filetypes=c('txt'))
datasetInput <- reactive({
inputfolders <- c(input$chosenfolders,
parseDirPath(volumes, input$fld))
updateCheckboxGroupInput(session, 'chosenfolders',
choices = inputfolders,
selected = inputfolders)
print(list('Input folders' = inputfolders))
})
output$selected <- renderPrint({
if (input$submitbutton>0) {
isolate(datasetInput())
} else {
return("Server is ready for calculation.")
}
})
}
shinyApp(ui = ui, server = server)

Shiny FilesButton start directory

i got a shiny app where the User must select a file to be processed further.
The shinyFilesButton lets me do exactly that - BUT, the file selection always starts at the root directory (in my case C:). Is it possible to let the file selection start at a specific directory? For example, i would like the file selection to start at "C:\Users\admin\Documents"
This would greatly improve usability.
Thank in advance!
Patrick
MWE
library(shiny)
# Define UI ----
ui <- fluidPage(
shinyFilesButton("filePath", "Please Select File", title = "Select File", multiple = FALSE,
buttonType = "default", class = NULL),
br(),
br(),
textOutput("inputFile")
)
# Define server logic ----
server <- function(input, output, session) {
volumes = getVolumes()
observe({
shinyFileChoose(input, "filePath", roots = volumes, session = session)
if(!is.null(input$filePath)){
# browser()
input_file_selected <- parseFilePaths(volumes, input$filePath)
output$inputFile <- renderText({
paste("File Path: ", as.character(input_file_selected$datapath))
})
}
})
}
# Run the app ----
shinyApp(ui = ui, server = server)
This is the role of the roots option:
shinyFileChoose(input, "filePath", roots = c(Documents = "C:/Users/admin/Documents"), session = session)

shinyFiles folder selection: display the default folder

I need to display selected folder for Shiny users, and I asked here how to do this (Display selected folder path in Shiny). It works but now I can't figure out how to show the default folder (for example, current directory) before the selection was made.
library(shiny)
library(shinyFiles)
ui <- fluidPage( # Application title
mainPanel(
shinyDirButton("dir", "Input directory", "Upload"),
verbatimTextOutput("dir", placeholder = TRUE)
))
server <- function(input, output) {
shinyDirChoose(
input,
'dir',
roots = c(home = '~'),
filetypes = c('', 'txt', 'bigWig', "tsv", "csv", "bw")
)
dir <- reactive(input$dir)
output$dir <- renderText({
parseDirPath(c(home = '~'), dir())
})
## change smth here... if output$dir is null, display getwd() but it doesn't work
observeEvent(ignoreNULL = TRUE,
eventExpr = {
input$dir
},
handlerExpr = {
home <- normalizePath("~")
datapath <<-
file.path(home, paste(unlist(dir()$path[-1]), collapse = .Platform$file.sep))
})
}
# Run the application
shinyApp(ui = ui, server = server)
I can think only of a conditional panel displaying some text if the folder wasn't selected. But I guess there should a better way to do this. Thank you!
Concerning "beyond" displaying you could save the datapath variable in a reactiveValue and set the working directory as the default:
global <- reactiveValues(datapath = getwd())
And the app:
library(shiny)
library(shinyFiles)
ui <- fluidPage( # Application title
mainPanel(
shinyDirButton("dir", "Input directory", "Upload"),
verbatimTextOutput("dir", placeholder = TRUE)
))
server <- function(input, output) {
shinyDirChoose(
input,
'dir',
roots = c(home = '~'),
filetypes = c('', 'txt', 'bigWig', "tsv", "csv", "bw")
)
global <- reactiveValues(datapath = getwd())
dir <- reactive(input$dir)
output$dir <- renderText({
global$datapath
})
observeEvent(ignoreNULL = TRUE,
eventExpr = {
input$dir
},
handlerExpr = {
home <- normalizePath("~")
global$datapath <-
file.path(home, paste(unlist(dir()$path[-1]), collapse = .Platform$file.sep))
})
}
# Run the application
shinyApp(ui = ui, server = server)

Display selected folder path in Shiny

I want my Shiny app to allow user specify a path to a folder (locally) and display the selected path. The following code works but I can't figure out how to hide "character(0)" in verbatimTextOutput until the folder was selected. I tried conditional panel (see commented out in my code) but can't figure out what to use as a condition here (because shinyDirButton is not a standard action button...). Thank you!
library(shiny)
library(shinyFiles)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
mainPanel(
shinyDirButton("dir", "Input directory", "Upload"),
#conditionalPanel(
#condition = "???",
verbatimTextOutput('dir')
#)
)
)
server <- function(input, output) {
shinyDirChoose(input, 'dir', roots = c(home = '~'), filetypes = c('', 'txt','bigWig',"tsv","csv","bw"))
dir <- reactive(input$dir)
output$dir <- renderPrint({parseDirPath(c(home = '~'), dir())})
observeEvent(
ignoreNULL = TRUE,
eventExpr = {
input$dir
},
handlerExpr = {
home <- normalizePath("~")
datapath <<- file.path(home, paste(unlist(dir()$path[-1]), collapse = .Platform$file.sep))
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
The closest question I was able to find is this but it doesn't solve my problem: R conditionalPanel reacts to output
In the server function, use renderText instead of renderPrint:
library(shiny)
library(shinyFiles)
# Define UI for application that draws a histogram
ui <- fluidPage( # Application title
mainPanel(
shinyDirButton("dir", "Input directory", "Upload"),
verbatimTextOutput("dir", placeholder = TRUE) # added a placeholder
))
server <- function(input, output) {
shinyDirChoose(
input,
'dir',
roots = c(home = '~'),
filetypes = c('', 'txt', 'bigWig', "tsv", "csv", "bw")
)
dir <- reactive(input$dir)
output$dir <- renderText({ # use renderText instead of renderPrint
parseDirPath(c(home = '~'), dir())
})
observeEvent(ignoreNULL = TRUE,
eventExpr = {
input$dir
},
handlerExpr = {
home <- normalizePath("~")
datapath <<-
file.path(home, paste(unlist(dir()$path[-1]), collapse = .Platform$file.sep))
})
}
# Run the application
shinyApp(ui = ui, server = server)

r shiny - upload all files from shinyDirChoose folder to server

I saved the path of a user-defined folder with shinyDirChoose. Now I want to upload files from that user's folder, but I cannot figure out how to do it.
1) All on the server end?
2) Feeding the file paths to fileInput somehow?
This is how I construct the file paths for the three files that should be uploaded.
### ui end, to browse to desired folder
ui = fluidPage(shinyDirButton('directory', 'Folder select', 'Please select a folder'))
### extracting the folder path
server = function(input, output, session) {
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
### constructing the 3 file paths
datpat <- renderText({
req(nchar(path1())>0)
datpat <- paste0(path1(),"/data.csv")
})
vispat <- renderText({
req(nchar(path1())>0)
vispat <- paste0(path1(),"/visit.csv")
})
statpat <- renderText({
req(nchar(path1())>0)
statpat <- paste0(path1(),"/statvisit.csv")
})
So now I have these paths, but how can I use them to upload the related content to the server? A simple read.csv unfortunately does not do the trick.
EDIT - but not there yet...
Working further with the great help #SBista provided, I think I'm approaching my goal, but see below code...
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
observe({
if(!is.null(path1)){
### vis1
vis1 <- reactive({
datpat <- paste0(path1(),"/visit.csv")
vis <- read.csv(datpat, header = input$header, sep = input$sep, quote = input$quote,
stringsAsFactors = FALSE)
vis
})
### dataruw1
dataruw1 <- reactive({
datpat <- paste0(path1(),"/data.csv")
dataruw <- read.csv(datpat, header = input$header, sep = input$sep, quote = input$quote,
stringsAsFactors = FALSE)
dataruw
})
}
})
Unfortunately, dataruw1 and vis1 do not seem to be generated, as I get a 'could not find function' error when trying to use the actual data with dataruw1() and vis1(). What am I missing? Any idea? Thanks a lot in advance!
I have modified your app to demonstrate that you can use read.csv to upload the file. For demonstration I am reading only one file from the folder and displaying the read data frame in a datatable.
library(shiny)
library(shinyFiles)
### ui end, to browse to desired folder
ui = fluidPage(shinyDirButton('directory', 'Folder select', 'Please select a folder'),
tableOutput(outputId = "datpat")
)
### extracting the folder path
server = function(input, output, session) {
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
### constructing the 3 file paths
observe({
if(!is.null(path1)){
output$datpat <- renderTable({
req(nchar(path1())>0)
datpat <- paste0(path1(),"/data.csv")
dat <- read.csv(datpat)
dat
})
}
})
}
shinyApp(ui = ui, server = server)
Hope it helps!
Happy to have found a solution! Big thanks to SBista once more, even though I did it a bit differently. The below code is not just a chunk (as in my original post) but fully functional, provided you browse to a folder that contains a data.csv file.
library(shiny)
library(shinyFiles)
library(htmltools)
##############################################################################
ui = navbarPage(
HTML("Title"),
tabPanel(HTML("<font size=3>Start</font>"),
sidebarPanel(width = 2,
shinyDirButton('directory', 'Folder select', 'Please select a folder'),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator', c(Comma=',',Semicolon=';',Tab='\t'), selected=';'),
radioButtons('quote', 'Quote', c(None='','Double Quote'='"','Single Quote'="'"), selected='"')),
mainPanel(
fluidRow(
column(6, tags$b(textOutput("text")))),
tags$hr(),
fluidRow(
column(6, dataTableOutput("table"))
)
)
)
)
server = function(input, output, session) {
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
dataruw1 <- eventReactive(input$directory, {
datpat <- paste0(path1(),"/data.csv")
dataruw <- read.csv(datpat, header = input$header, sep = input$sep, quote = input$quote,
stringsAsFactors = FALSE)
dataruw
})
output$text <- renderText({
path1()
})
output$table <- renderDataTable({
dataruw1()
})
}
shinyApp(ui = ui, server = server, options = list(launch.browser=TRUE))

Resources