There is this piece of code in which basically from UI page in which I want to select the file names for through checkbox and after selecting those, then clicking on download button selected files will get downloaded. I am stuck at UI i am unable to get those checkboxes on UI.
its showing the output as
[object] [Object]
the code is below -
ui <- fluidPage(
verbatimTextOutput("links_list")
)
server <- function(input, output, session) {
get.files <- reactive({
list.files("/Users/harshmeetsingh/Downloads/")
})
obsList <- list()
output$links_list <- renderUI({
lapply(as.list(1:length(get.files())), function(i)
{
btName <- get.files()[i]
print(btName)
# creates an observer only if it doesn't already exists
if (is.null(obsList[[btName]])) {
obsList[[btName]] <<- btName
}
fluidRow(checkboxInput(btName, get.files()[i]) )
})
})
output$downloadzip<-downloadHandler(
filename = function(){
paste0("Extract.zip")
},
content = function(file){
files <- NULL;
for (i in 1:length(obsList)){
if(input[[obsList[[i]]]])
files <- c(paste("output_file/",obsList[[i]],sep=""),files)
}
#create the zip file
zip(file,files)
},
contentType = "application/zip"
)
tempText <- eventReactive({input$TempTest},{
l<-c()
for (i in 1:length(obsList)){
if(input[[obsList[[i]]]])
l<-c(l,paste("output_file/",obsList[[i]],sep=""))
}
return(paste(l) )
},
ignoreInit = TRUE)
output$Temp <- renderPrint({ tempText()})
}
shinyApp(ui=ui,server=server)
We can use checkboxGroupInput() to select all the files. input$files_chosen will be a list with all the filenames selected.
Notice that this app is showing the files in the home directory. This can be modified changing the path supplied in setwd().
app:
library(shiny)
#to use relative paths inside zip function
setwd('~')
ui <- fluidPage(
downloadButton('downloadzip'),
uiOutput("links_list")
)
server <- function(input, output, session) {
get.files <- reactive({
list.files()
})
output$links_list <- renderUI({checkboxGroupInput(inputId = 'files_chosen',
label = 'Choose Files',
choices = get.files())
})
output$downloadzip <- downloadHandler(
filename = function(){
"Extract.zip"
},
content = function(file){
#create the paths to look for the files.
files <- input$files_chosen
#create the zip file
zip(zipfile = file, files = files)
},
contentType = "application/zip"
)
}
shinyApp(ui=ui,server=server)
Related
So I have this shiny app which includes a checkbox button:
library(bold)
library(stringr)
library(readr)
library(shiny)
library(shinyWidgets)
grades2<-function(groups,inputz,coordz){
taxon<-bold_seqspec(taxon=groups, format = "tsv")
taxon2<-taxon[taxon$species_name!=""|is.na(taxon$species_name),]
taxon2<-taxon2[!(taxon2$bin_uri == "" | is.na(taxon2$bin_uri)), ]
taxon2$base_number=str_count(taxon2$nucleotides, pattern="[A-Z]")
taxon2<-taxon2[taxon2$base_number>=inputz,]
if (coordz==TRUE){
taxon2<-taxon2[!(is.na(taxon2$lat)) | taxon2$country!="",]
}else{
taxon2<-taxon2
}
assign('taxon2',taxon2,envir=.GlobalEnv)
}
ui <- navbarPage(title=tags$h3("APP"),tabPanel(column(12,align="center",tags$h4("Download"),tags$br(),
sliderInput("seqsize", "Mininum number of base pairs for sequences in reference library:",min = 0, max = 1000, value = 500),textOutput("SliderText"),
checkboxInput("rmvpaises", "Remove records without data on country of origin or latitude", TRUE),
textInputAddon(inputId="taxa2",addon=icon("search"),width="500px",label=tags$h5(tags$strong("Enter the name of the taxonomic group or groups separated by commas, without spaces:")),placeholder="Example: Carnivora,Ursidae,Artiodactyla,Soricomorpha"),
downloadButton("downloadData_2","Download"))))
server <- function(input, output){
#sliderValues <- reactive({as.integer(input$seqsize)})
#output$values <- renderText({
# sliderValues()
#})
taxaInput_2 <- reactive({grades2(unlist(strsplit(input$taxa2, ",")),as.integer(input$seqsize),input$rmvpaises)})
output$downloadData_2 <- downloadHandler(
filename = function() {
paste(input$taxa2,sep_out=",", ".tsv")
},
content = function(file) {
shiny::withProgress(
value=10,
{
shiny::incProgress(10/10)
write_tsv(taxaInput_2(), file)
}
)
}
)
output$value <- renderText({ input$rmvpaises })
}
shinyApp(ui=ui,server=server)
For some reason while using the app, the check box is non-responsive. It doesn't change.
The input of the check box is being used in the initial function "grades2" and it is the "coordz" argument.
Thank you so much for any answer
You're missing the non-optional argument title for tabPanel. Consequently, it's using the column UI element as the title for the tab which I'm assuming is doing weird stuff with the z-index.
You need an observer to update the checkboxInput on the server side. The checkbox works fine in this code
grades2<-function(groups,inputz,coordz){
taxon<-bold_seqspec(taxon=groups, format = "tsv")
taxon2<-taxon[taxon$species_name!=""|is.na(taxon$species_name),]
taxon2<-taxon2[!(taxon2$bin_uri == "" | is.na(taxon2$bin_uri)), ]
taxon2$base_number=str_count(taxon2$nucleotides, pattern="[A-Z]")
taxon2<-taxon2[taxon2$base_number>=inputz,]
if (coordz) {
taxon2<-taxon2[!(is.na(taxon2$lat)) | taxon2$country!="",]
}else{
taxon2<-taxon2
}
assign('taxon2',taxon2,envir=.GlobalEnv)
}
ui <- navbarPage(title=tags$h3("APP"),tabPanel(value="Panel1" , column(12,align="center",tags$h4("Download"),tags$br(),
sliderInput("seqsize", "Mininum number of base pairs for sequences in reference library:",min = 0, max = 1000, value = 500),textOutput("SliderText"),
checkboxInput("rmvpaises", "Remove records without data on country of origin or latitude", TRUE),
textInputAddon(inputId="taxa2",addon=icon("search"),width="500px",label=tags$h5(tags$strong("Enter the name of the taxonomic group or groups separated by commas, without spaces:")),placeholder="Example: Carnivora,Ursidae,Artiodactyla,Soricomorpha"),
downloadButton("downloadData_2","Download"))))
server <- function(input, output, session){
#sliderValues <- reactive({as.integer(input$seqsize)})
#output$values <- renderText({
# sliderValues()
#})
observe({
updateCheckboxInput(session, "rmvpaises", value=input$rmvpaises)
})
taxaInput_2 <- reactive({grades2(unlist(strsplit(input$taxa2, ",")),as.integer(input$seqsize),input$rmvpaises)})
output$downloadData_2 <- downloadHandler(
filename = function() {
paste(input$taxa2,sep_out=",", ".tsv")
},
content = function(file) {
shiny::withProgress(
value=10,
{
shiny::incProgress(10/10)
write_tsv(taxaInput_2(), file)
}
)
}
)
output$value <- renderText({ input$rmvpaises })
}
shinyApp(ui=ui,server=server)
I want to initialize the download of a file in R Shiny when a button is pressed and do some checks before generating the file.
I've fooled arround with the downloadHandler (https://shiny.rstudio.com/gallery/file-download.html). But I want to catch the event of another button, do some things and checks with the data and when everything went well generate the file and initialize the download without having to press the download button from downloadHandler.
I've implemented most checks for now in the downloadHandler, but it now generates a failed download when some checks aren't fulfilled. I don't like the behavior.
output$downloadData <- downloadHandler(
filename = function() { paste("DATA_EXPORT-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
withProgress(message = 'Export data', value = 0, {
# Number of steps
n <- 3
incProgress(1/n, detail = "Pre checks and get data")
# checks if inputs for get_data are well defined
dataSet <- get_data(blabla)
incProgress(1/n, detail = "Post Proces and check")
incProgress(1/n, detail = "generate flatfile")
write.csv(dataSet, file, row.names = FALSE)
})
}
)
To elaborate my comment, a minimal example:
library(shiny)
library(shinyjs)
# function which checks the data; returns TRUE or FALSE
checkData <- function(dat){
TRUE
}
# function which transforms the data; returns NULL if check not TRUE
processData <- function(dat){
if(checkData(dat)){
# do something with dat
names(dat) <- toupper(names(dat)) # for our example
return(dat)
}else{
return(NULL)
}
}
ui <- fluidPage(
useShinyjs(),
conditionalPanel(
"false", # always hide the download button
downloadButton("downloadData")
),
actionButton("check", "Download")
)
server <- function(input, output, session){
dat <- mtcars
finalData <- reactiveVal() # to store the processed data
observeEvent(input$check, {
if(!is.null(df <- processData(dat))){
finalData(df)
runjs("$('#downloadData')[0].click();")
}else{
# something which throws an alert message "invalid data"
# (eg with shinyBS::createAlert or shinyWidgets::sendSweetAlert)
}
})
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(finalData(), file)
}
)
}
shinyApp(ui, server)
So I want to have a Shiny page which:
A) Allows the user to upload a .xls file;
B) Offers that file back to the user for download as a .csv file;
C) Prints the head of the file in the Shiny app to ensure that it was properly read.
Here is the code I am using:
# Want to read xls files with readxl package
library(readxl)
library(shiny)
## Only run examples in interactive R sessions
if (interactive()) {
ui <- fluidPage(
fileInput("file1", "Choose File", accept = ".xls"),
tags$hr(),
uiOutput("downloader"),
htmlOutput("confirmText", container = tags$h3),
tableOutput("listContents")
)
server <- function(input, output) {
theOutput <- reactiveValues(temp = NULL, df = NULL, msg = NULL, fn = NULL)
observeEvent(input$file1, {
theOutput$fn <- paste('data-', Sys.Date(), '.csv', sep='')
theOutput$temp <- read_xls(input$file1$datapath)
theOutput$msg <- paste("File Contents:")
theOutput$df <- write.csv(theOutput$temp,
file = theOutput$fn,
row.names = FALSE)
})
output$confirmText <- renderText({
theOutput$msg
})
output$listContents <- renderTable({
head(theOutput$temp)
})
output$downloader <- renderUI({
if(!is.null(input$file1)) {
downloadButton("theDownload", label = "Download")
}
})
output$theDownload <- downloadHandler(
filename = theOutput$fn,
content = theOutput$df
)
}
shinyApp(ui, server)
}
The Shiny page renders correctly, it accepts the upload with no problems, it prints out the head of the .csv with no problems, and it creates a properly formatted "data-{today's date}.csv" file in the same directory as the app.R file.
Problem is, when I hit the download button I get the error message:
Warning: Error in download$func: attempt to apply non-function
[No stack trace available]
Can someone tell me what I am doing wrong?
Thanks to the comments above, this is the solution I found (with my comments added, to show where the code changed):
library(readxl)
library(shiny)
if (interactive()) {
ui <- fluidPage(
fileInput("file1", "Choose File", accept = ".xls"),
tags$hr(),
uiOutput("downloader"),
htmlOutput("confirmText", container = tags$h3),
tableOutput("listContents")
)
server <- function(input, output) {
theOutput <- reactiveValues(temp = NULL, msg = NULL)
observeEvent(input$file1, {
# Do not try to automate filename and the write.csv output here!
theOutput$temp <- read_xls(input$file1$datapath)
theOutput$msg <- paste("File Contents:")
})
output$confirmText <- renderText({
theOutput$msg
})
output$listContents <- renderTable({
head(theOutput$temp)
})
output$downloader <- renderUI({
if(!is.null(input$file1)) {
downloadButton("theDownload", label = "Download")
}
})
output$theDownload <- downloadHandler(
# Filename and content need to be defined as functions
# (even if, as with filename here, there are no inputs to those functions)
filename = function() {paste('data-', Sys.Date(), '.csv', sep='')},
content = function(theFile) {write.csv(theOutput$temp, theFile, row.names = FALSE)}
) }
shinyApp(ui, server) }
The fact that content takes an argument (named here "theFile"), which is not called anywhere else, is what was throwing me off.
I'm new to shiny.
I have a very basic question but I can't find a solution here on stackoverflow.
I am using directory Input function created by wleepang (https://github.com/wleepang/shiny-directory-input).
I wrote a function read_files that rbind all files in the directory selected.
I can display this table with renderTable, this works perfectly. But I do not manage to save this table to work with later (check for missing data, add columns, draw ggplots..) and to download is with write.xlsx
ui <- fluidPage(
directoryInput('directory', label = 'select a directory'),
actionButton("upload", label="Hochladen"),
downloadButton("download", label="Runterladen")
)
server <- function(input, output, session) {
#this part is to set the directory
observeEvent(
ignoreNULL = TRUE,
eventExpr = {
input$directory
},
handlerExpr = {
if (input$directory > 0) {
path = choose.dir(default = readDirectoryInput(session, 'directory'))
updateDirectoryInput(session, 'directory', value = path)
}})
#now comes the actual code
observeEvent(input$upload,{
df <- read_files(readDirectoryInput(session, 'directory'))
})
How can I access this df later?
output$downloadData <- downloadHandler(
filename = function() {
paste('tabelle', '.csv', sep="") },
content = function(file) {
write.xlsx(df, file)
}
)
}
And my second question how can I download it as a xlsx file in the set directory?
my global.r with the read_files function
source('directoryInput.R')
read_files = function(inDir, pat="*.csv", readMe=read.csv2){
files = list.files(inDir, pattern=pat)
files = lapply(files, function(x) file.path(inDir, x))
df = do.call(rbind, lapply(files, readMe))
return(df)
}
I have saved the element using a reactive function
upload_data <- eventReactive(input$upload, {
read_files(readDirectoryInput(session, 'directory')) })
and can access it through upload_data() this works for me
I have created a shiny app that uses session$clientData to get parameter values to the server. It works great, however, I would also like to be able to initiate a download through the url, e.g:
localhost:8100/?plot=a&title=mytitle&download=1
and then in server.R, something like:
if(session$clientData$download == "1"){
download()
}
Hence, is it possible to initiate the downloadHandler() in server.R?
Thanks!
I am not sure I have correctly understood what you are trying to do. What I have understood is that you would like a download to be initiated when the query string download=1 is present in the url. You could do this by injecting some javascript to open the link when the required query string is detected. There will be some problems however.
Your browser will most likely block the pop up. You will need to wait a sufficient length of time before you fire the code (I have chosen 5 seconds).
require(shiny)
runApp(list(
ui = bootstrapPage(
tags$head(tags$script(HTML('
Shiny.addCustomMessageHandler("jsCode",
function(message) {
eval(message.value);
}
);
'))),
downloadLink('downloadData', 'Download'),
verbatimTextOutput("summary")
),
server = function(input, output, session) {
data <- seq(100)
output$downloadData <- downloadHandler(
filename = function() {
paste('data-', Sys.Date(), '.csv', sep='')
},
content = function(file) {
write.csv(data, file)
}
)
output$summary <- renderText({
cnames <- names(session$clientData)
allvalues <- lapply(cnames, function(name) {
item <- session$clientData[[name]]
if (is.list(item)) {
list_to_string(item, name)
} else {
paste(name, item, sep=" = ")
}
})
paste(allvalues, collapse = "\n")
})
observe({
query <- parseQueryString(session$clientData$url_search)
if(!is.null(query$download)){
if(query$download == 1){
jsinject <- "setTimeout(function(){window.open($('#downloadData').attr('href'))}, 5000);"
session$sendCustomMessage(type = 'jsCode', list(value = jsinject))
}
}
})
}
))