The data in my shiny application takes a few seconds to be processed.
I have a download button and I would like it to be either unclickable until the data are prepared or have the download handler wait until prepared.
At the moment clicking the download button before 5 secs returns the default html file and then after 5 secs it behaves as expected.
My current solution is to use `shinyjs::hide/show. I’ve shown this below.
Is this best practice? Also, why the shinyjs::useShiny() at the start? It seems unique to that package.
ui <- fluidPage(
shinyjs::useShiny(),
shinyjs::hidden(downloadButton("downloadData", "Download"))
)
server <- function(input, output) {
# Our dataset
data <- mtcars
if(is.null(mtcars)){shinyjs::hide(“downloadData”)}
else{shinyjs::show(“downloadData”)}
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)}
)
}
shinyApp(ui, server)
What you describe is perfectly reasonable and has been suggested on stackoverflow in the past. You can also use disable/enable instead of hide/show, whatever you feel is a better user experience.
The useShinyjs() is required to set up all the R <--> JavaScript communication that is happening. Without it, when you try to call a shinyjs function from the server, nothing will happen because the UI didn't get initialized with the javascript. Some other pacakges have also adopted this pattern since I made shinyjs, especially packages that also deal with javascript.
Related
So I have a shiny app (https://github.com/tadeu95/BAGs) (http://tadeu-apps.shinyapps.io/bags) and I have several download buttons. Recently what has started to happen is that when I click the download button it activates two times and downloads the same file twice. The thing is that the app worked for almost a year without any problem.
I've tried on chrome, edge and mozzila and happens every time. I don't know what happened because I didn't touch the part of the code where the downloads are implemented.
One thing I've just discovered is that if instead of clicking the download button with the left button of the mouse, I click the right button and choose "open link in a new tab", it downloads the file correctly only once.
This is a short reproducible app, I advise that you give as input "ursidae" as it downloads the file pretty quickly:
library(bold)
library(readr)
library(shiny)
library(shinyWidgets)
grades2<-function(groups){
taxon9<-bold_seqspec(taxon=groups, format = "tsv")
}
ui <- fluidPage(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"),downloadBttn("downloadData_2",size="sm","Download"))
server <- function(input, output) {
taxaInput_2 <- reactive({grades2(unlist(strsplit(input$taxa2, ",")))})
output$downloadData_2 <- downloadHandler(
filename = function() {
paste(input$taxa2,sep_out=",", ".tsv")
},
content = function(file) {
shiny::withProgress(
message=paste0("Downloading and annotating library for ",input$taxa2,sep_out=","), detail='This may take several minutes',
value=10,
{
shiny::incProgress(10/10)
write_tsv(taxaInput_2(), file)
}
)
}
)
}
shinyApp(ui=ui,server=server)
If anyone has any idea what the reason might be, I will be very thankful.
I am setting up a Shiny app that allows the user to download a custom dataset. Following the tutorial, I set up the downloadHandler following the example given in the docs (reproduced here, since the same thing happens if I copy and paste this).
ui <- fluidPage(
downloadLink("downloadData", "Download")
)
server <- function(input, output) {
# Our dataset
data <- mtcars
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)
}
)
}
shinyApp(ui, server)
Problem:
This issue only comes up on my Linux* system and seems to work just fine on a Mac. The download and everything works just fine, but the "Save" GUI does not offer me the right file name. There is no error message or warning. Based on my input,
I'd expect it to give me data-TIME.csv, i.e. the input to filename. (It does not work either if I give it simple string in that slot).
but it offers me DownloadData or whatever name I give to the output variable (cf. screenshot).
Question:
Is this a OS issue as I suspect, or am I doing something wrong?
How do i fix this? Can I get this to work on any system?
Thanks!
I'm running elementary OS 0.4 Loki, Built on "Ubuntu 16.04.2 LTS", GTK version: 3.18.9. & RStudio 1.0.143
If you are using the Rstudio Browser to test you App this could be the problem. I have the same issue on Windows.
When I use the Rstudio Browser the filename is not properly hand over, but if I use Firefox everything works fine. Your code works also fine in my Firefox.
I am new to Shiny and I have created a really simple shiny app:
library(shiny)
ui <- fluidPage(
fluidRow(column(7,dataTableOutput('dto')))
)
server <- function(input,output){
output$dto <- renderDataTable({MYTABLE})
}
runApp(list(ui=ui,server=server))
Is there any way to put an option to download the result of the table (doesn't matter if is CSV, XLSX...)
cheers
That's pretty easy with downloadButton() or downloadLink() in combination with downloadHandler if you make the data itself a reactive expression. Then you can download whatever you send to output using the same reactive expression.
A small example:
library(shiny)
ui <- fluidPage(
# This one is linked by the id 'download'
downloadButton('download',"Download the data"),
fluidRow(column(7,dataTableOutput('dto')))
)
server <- function(input,output){
# Reactive expression with the data, in this case iris
thedata <- reactive(iris)
output$dto <- renderDataTable({thedata()})
output$download <- downloadHandler(
filename = function(){"thename.csv"},
content = function(fname){
write.csv(thedata(), fname)
}
)
}
runApp(list(ui=ui,server=server))
Keep in mind:
the argument content of downloadHandler must be a function producing a file! It should take one argument for the connection/file name. In this example it is a csv file, but for eg images you can use png() and dev.off(), for ggplots you can use ggsave(), ...
the argument filename does not have to be a function, but I found it works
better that way. Especially when working with reactive expressions for the file name.
you link the downloadHandler and the downloadButton through the output list: the id of downloadButton is the name of the output element returned by downloadHandler.
EDIT:
Some people try to use download.file() for this, but that's wrong as well. The function download.file() works when used on the user side, not the server side. It lets you download files from the internet to the computer that is calling the function. If you'd use that in a Shiny application, it would work when run locally. That's because user and server are the same machine. However, when deploying your app on a Shiny Server, download.file() would essentially be downloading files TO the server, not from.
A slightly alternative solution based directly on the datatable / DT extension buttons.
I am shamelessly borrowing the example data from Joris...
library(shiny)
library(DT)
ui <- fluidPage(
# This one is linked by the id 'download'
fluidRow(column(7,dataTableOutput('dto')))
)
server <- function(input,output){
# Reactive expression with the data, in this case iris
thedata <- reactive(iris)
#the extensions parameter coupled with the options list does the trick
output$dto <- renderDataTable(thedata(), extensions = 'Buttons',
options = list(dom = 'Bfrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print'))
)
}
runApp(list(ui=ui,server=server), launch.browser=TRUE) #now runs by default in the external browser.
This will work with different outputs and personally I like the cleaner look. Just make sure that you are running the demo in the external browser. Otherwise it won't work.
I have to execute the app in the browser because the filename isn't working. I use
runApp(list(ui=ui,server=server),launch.browser = T)
and it works perfectly for me.
If you don't want to use launch.browser=TRUE you can write the filename and the extension for example .csv at the end of the filename when you use the download button in the shiny app.
I've run into a problem with downloadHandler() in Shiny:
If I want to download any file via this function, the filename in the download window is the same as the name of the output-variable (in the example: "downloadData"), but not as it is declared in "filename=" in downloadHandler() (which should be "data-2017-02-13.csv").
Note that the following example is from the downloadHandler() - help page, so I guess there is a general problem with R or RStudio in which I write R scripts.
Additionally when I open the shiny app in a web browser, the problem vanishes.
This partially solves it, but I would still like to know why shiny is behaving differently inside RStudio and a web browser.
## Only run examples in interactive R sessions
if (interactive()) {
ui <- fluidPage(
downloadLink("downloadData", "Download")
)
server <- function(input, output) {
# Our dataset
data <- mtcars
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)
}
)
}
shinyApp(ui, server)
}
and here the download window I get:
I had the same issue when I used the RStudio preview window and was able to solve this issue by always opening a browser with the command
runApp(launch.browser = TRUE)
In my Shiny app I want to open several URL's with a short delay between opening.
Here is some example code that works just fine when I run the app in my RStudio.
library(shiny)
URLs <- c("http://www.google.com", "http://www.stackoverflow.com")
ui <- fluidPage(
actionButton(
"click",
"Click here to open several browser tabs"
)
)
server <- function(input, output){
observeEvent(input$click, {
for (i in URLs){
browseURL(i)
Sys.sleep(1) #Short delay of 1 second
}
})
}
shinyApp(ui, server)
However, when I run this app on shinyapps.io, browseURL() doesn't work (as mentioned here).
Does anyone know how to open multiple browser tabs with a short delay between opening them, so that it also works when the app is deployed on shinyapps.io?
Would it be possible with R code or is JavaScript necessary?
This is a pretty old question, but answering in case others stumble upon while searching.
As mentioned in the reference you linked, I think you need to use some JS to accomplish this task. Below is an example of using the shinyjs package to define a shiny compatible browseURL function. Once we have the function defined we add a few lines to the ui and then call it in the server as js$browseURL().
Note that a pop-up blocker might block the effects of opening multiple tabs. Check your blocker settings if things don't seem to work.
library(shiny)
library(shinyjs)
# define js function for opening urls in new tab/window
js_code <- "
shinyjs.browseURL = function(url) {
window.open(url,'_blank');
}
"
URLs <- c("http://www.google.com", "http://www.stackoverflow.com")
ui <- fluidPage(
# set up shiny js to be able to call our browseURL function
useShinyjs(),
extendShinyjs(text = js_code, functions = 'browseURL'),
actionButton(
"click",
"Click here to open several browser tabs"
)
)
server <- function(input, output){
observeEvent(input$click, {
for (i in URLs){
js$browseURL(i)
Sys.sleep(1) #Short delay of 1 second
}
})
}
shinyApp(ui, server)