R - Count Shiny Download Button Clicks

R - count Shiny download button clicks

I think there is no build-in method. But you could build it yourself.

You can do this by adding a click listener to the button with javascript:

  observe({
if(is.null(input$rnd)){
runjs("
var click = 0;
Shiny.onInputChange('rnd', click)
var dwnldBtn = document.getElementById('dwnldBtn')
dwnldBtn.onclick = function() {click += 1; Shiny.onInputChange('rnd', click)};
")
}
})

The output from Shiny.onInputChange('rnd', click) will be accessible in Shiny via input$rnd.

Edit: For multiple buttons you can use:

  observe({
for(btn1 in 1:2){
if(is.null(input[[paste0("rnd", btn1)]])){
runjs(
paste0("
var counter", btn1 ,"= 0;
var dwnldBtn = document.getElementById('", paste0("dwnldBtn", btn1), "')
dwnldBtn.onclick = function() {counter", btn1, " +=1; Shiny.onInputChange('", paste0("rnd", btn1), "', counter", btn1,")};
")
)
}
}
})

For a working example see below:

   library(shiny)
library(shinyjs)
data <- matrix(1:20, nrow=5)

ui <- fluidPage(title = 'Count Button Clicks',
useShinyjs(),
fluidRow(style = "padding-bottom: 20px;",
column(width=6,
textOutput("actionclickCount"),
br(),
textOutput("downloadclickCount")
),
column(width=6,
actionButton("actionBtn", "Action Button"),
br(),
downloadButton("dwnldBtn", "Download Button")
)
)
)

server <- function(input, output, session) {
output$actionclickCount <- renderText({
paste('Action Button Clicks =',input$actionBtn)
})

output$downloadclickCount <- renderText({
paste('Download Button Clicks =', input$rnd)
})

output$dwnldBtn <- downloadHandler(
filename = 'data.csv',
content = function(file){
write.csv(data, file)
},
contentType = 'csv'
)

observe({
if(is.null(input$rnd)){
runjs("
var click = 0;
Shiny.onInputChange('rnd', click)
var dwnldBtn = document.getElementById('dwnldBtn')
dwnldBtn.onclick = function() {click += 1; Shiny.onInputChange('rnd', click)};
")
}
})

}

runApp(shinyApp(ui = ui, server = server), launch.browser = TRUE)

download count in shinyapps.io

I needed to do that once, so I had some code lying around. It basically kept track of everything in a csv that I appended to. Here I built it into a shiny test platform.

  • it uses the session$token for the id (maybe there is something better)
  • it uses write.table and read.table because they behave better with the append option.
  • it increments the count by calling out to writetolog in the shiny download handler but you can also increment the count manually with an extra button (which is only for test purposes obviously)
  • It has two output, one is a summary of the log, the other is a dump of what is in the log. These are for debugging as the downloadHandler can be a bit "challenging" at times when interacting with all this reactivity.

Here is that code modified to be an example like about what you need:

library(shiny)

logfname <- "log.csv"
writetolog <- function(newcount,newsessionid,operation){
time <- format(Sys.time(), "%Y-%m-%d %H:%M:%S %Z")
df <- data.frame(time=time,count=newcount,sessionid=newsessionid,operation=operation)
doappend <- file.exists(logfname)
if (doappend){
write.table(df,logfname,append=T,quote=F,col.names=F,sep=",",row.names=F)
} else {
write.table(df,logfname,append=F,quote=F,sep=",",row.names=F)
}
}
getcounts <- function(){
if (!file.exists(logfname)){
return(list(count=0,sessioncount=0))
}
df <- read.table(logfname,header=T,sep=",")
nr <- nrow(df)
rlst <- list(count=sum(df$count),sessioncount=length(unique(df$sessionid)),
lastop=df$operation[nr],lasttime=df$time[nr])
return(rlst)
}

ui <- fluidPage(
titlePanel("Keep a download log"),
sidebarLayout(
sidebarPanel(
actionButton("inccount","Increment Count"),
actionButton("getcount","Refresh Summary"),
actionButton("showlog","Show Log"),
downloadButton("dodownload", "Save to .csv")
),
mainPanel(
h2("Summary of Download Log"),
verbatimTextOutput("showcount"),
h2("Dump of Download Log"),
verbatimTextOutput("loglog")
)
)
)

server <- function(input, output,session) {
observeEvent(input$inccount,{
print("writetolog")
writetolog(1,session$token,"inc count")
})

output$showcount <- renderPrint({
input$getcount
rv <- getcounts()
time <- format(Sys.time(), "%Y-%m-%d %H:%M:%S %Z")
print(sprintf("%s - count:%d sessioncount:%d",time,rv$count,rv$sessioncount))
})
output$loglog <- renderPrint({
input$showlog
if (!file.exists(logfname)) return(NULL)
ldf <- read.csv(logfname)
print(ldf)
})

output$dodownload<-downloadHandler(
filename = function() {
paste(input$table_name, '.csv', sep='')
},
content = function(file) {
write.csv(mtcars, file)
writetolog(1,session$token,"save file")
}
)
}
shinyApp(ui = ui, server = server)

Screen shot:

Sample Image

R Shiny App- How to get download button working and how to display the number of rows?

Standard Download

This will download the original data set.

Not sure what you want to name the downloaded file so I've hard-coded it to test.csv.

        output$downloadData <- downloadHandler(
filename = function() {
paste("test.csv", sep = "")
},
content = function(con) {
write.csv(data, con, row.names = TRUE)
}
)

Filtered Download

This will subset the data based on what year, country and continent is selected and download that.
The filename will be made up of the selections delimited by a dash, unless no selections have been made, then the file name will be 'AllData.csv'.

        output$downloadData <- downloadHandler(
filename = function() {
selected <-c()
if (input$year != "All") {
selected <-c(selected, input$year)
}
if (input$country != "All") {
selected <-c(selected, input$country)
}
if (input$continent != "All") {
selected <-c(selected, input$continent)
}
if (length(selected) == 0) {
selected <- c("AllData")
}

paste0(paste(selected, collapse="-"), ".csv")
},
content = function(con) {
if (input$year != "All") {
data <- df[df$Year == input$year,]
}
if (input$country != "All") {
data <- df[df$Country == input$country,]
}
if (input$continent != "All") {
data <- df[df$Continent == input$continent,]
}
write.csv(data, con, row.names = TRUE)
}
)

Adding a download button to shiny, which prints the output of the server function

As You didnt post reproducible example, i assume that You do not have any problems with plotting and you can see the plot in Your app, please try this:

  1. Place Your whole code inside of the function, like:

    testplot <- function() {
    if (input$Select1 == "Absolute Worthaufigkeiten") {
    if (input$Select2 == "AFD") {
    AAA %>%
    filter(AFD > 2) %>%
    ggplot(aes(word, AFD, Jahr)) +
    geom_col(colour = "white", fill = "red2")
    }
    else{
    if (input$Select2 == "CDU") {
    AAA %>% ...
    }
    }
    }
    }
  2. Render the function testplot():

    output$Plot <- renderPlot({testplot()})
  3. Download the plot using downloadHandler():

    output$down <- downloadHandler(
    filename = function() {
    paste("AAA", input$var3, sep = ".")
    },
    content = function(file) {
    if (input$var3 == "pdf") {
    pdf(file, width = 30, height = 20)
    }
    else{
    png(file, width = 1200, height = 800, units = "px", pointsize = 12, bg = "white", res = NA)
    }
    print(testplot())
    dev.off()
    }
    )

Saving time on clicking action button in shiny

Use global variables would work. Example below (edited to use per-session global variable).

library(shiny)

ui <- shinyUI(fluidPage(
titlePanel("Header"),
sidebarLayout(
sidebarPanel(
actionButton("start", "Start"),
tags$br(),
actionButton("end", "End"),
tags$br(),
downloadButton("downloadData", "Download")
),

mainPanel(

)
)
))

server <- shinyServer(function(input, output) {

starttime <- NULL
endtime <- NULL

observeEvent(input$start, {
starttime <<- Sys.time()
})

observeEvent(input$end, {
endtime <<- Sys.time()
})

output$downloadData <- downloadHandler(
filename = function() {
"download.csv"
},
content = function(file) {
data <- data.frame(start=starttime, end=endtime)
write.csv(data, file, row.names = F)
}
)

})

shinyApp(ui = ui, server = server)

Shiny Application, Download button for graphs

This should work for you:

server.R:

library(shiny)
shinyServer(function(input,output,session){
observe({
inFile<-input$file1
#print(inFile)
if(is.null(inFile)) return(NULL)
dt = read.csv(inFile$datapath, header=input$header, sep=input$sep)
updateSelectInput(session, "product", choices = names(dt))
updateSelectInput(session, "familia", choices = c("realAll","realline","realplus","real0to1","counts","binom"))
})
testplot <- function(){
require(gamlss)
inFile<-input$file1
dt = read.csv(inFile$datapath, header=input$header, sep=input$sep)
k<-input$k
m <- fitDist(dt[,input$product], type=input$familia, k=k)
par(mfrow=c(2, 2))
for (i in 1:4) {
denst <- density(dt[,input$product])
res <- histDist(dt[,input$product], family=names(m$fits)[i],
main=names(m$fits)[i],
xlab=input$product,
line.wd=3,
line.ty=1,
line.col='dodgerblue2',
ylim=c(0, 1.3 * max(denst$y)))
param <- c('mu', 'sigma', 'nu', 'tau')
np <- length(res$parameters)
fun1 <- function(x) eval(parse(text=x))
hat.param <- sapply(as.list(paste('res$', param[1:np], sep='')),
fun1)
hat.param <- round(hat.param, digits=2)
txt <- paste('hat(', param[1:np], ')==', hat.param, sep='')
txt <- paste(txt, collapse=', ')
legend('topright', bty='n',
legend=eval(parse(text=paste('expression(', txt, ')'))))
}
}

output$distPlot <- renderPlot({testplot()})

output$descarga<-downloadHandler(
filename=function(){
paste("grafica","png",sep=".")
},content=function(file){
png(file)
print(testplot())
dev.off()
}
)

})

I wrapped Your code inside of the function (testplot()) which i have further used to renderPlot and inside of downloadHandler.

*For the future it would be better if you give/attach sample data, so Your code could be easily run in R

Display download button in Shiny R only when output appears in Main Panel

On server side you can use:

output$download <- renderUI({
if(!is.null(input$file1) & !is.null(input$file2)) {
downloadButton('OutputFile', 'Download Output File')
}
})

and on ui side you replace the download button with:

uiOutput("download")

In R Shiny, how to invoke download handler from radio buttons?

You may also stick with observeEvent:

  observeEvent(input$mainPanelBtnTab2,{
req(input$mainPanelBtnTab2 == "Downloads")
showModal(modalDialog(
selectInput("downloadItem","Selection:",c("Yield plot")),
downloadButton("download", "Download")
))}
) # close observeEvent

Or use if instead of req as @RonakShah did.

How to have a single download button for all datatables in R shiny webpage

(a) If you only want "one downloadButton visible in the header common to all pages that downloads the table in the active page or tab", it needs firstly to know the active page and tab based on the page / tab IDs. (b) If you only need a single button to download all the tables, you can download them into a .xlsx file (see download data onto multiple sheets from shiny). (c)If you need a button for each tab, place the button in each tab and you can simply save table as .csv.
Here is the code for situation (a).

library(shiny)
library(shinydashboard)
library(DT)

ui <- dashboardPage(
dashboardHeader(title = "Header",
dropdownMenuOutput("updatedTimeOutput"),
dropdownMenu(type = "notifications",
badgeStatus = "warning",
icon = icon("bullhorn", "fa-lg"),
notificationItem(icon = icon("bullhorn", "fa-1x"),
status = "info",
text = tags$span(
tags$b("Please notice!")
)
))),
dashboardSidebar( sidebarMenu(id = "pages", # use unique id for pages
menuItem("Page1", tabName = "page1"),
menuItem("Page2", tabName = "page2"))),
dashboardBody(

# Add download button
downloadButton('downloadData', 'Download Table',
style="font-weight:bold;"
),
helpText(
hr(style = "border-top: 1px solid #000000;"),
),

tabItems(
tabItem(
tabName = "page1",

tabsetPanel(id="tabs",

tabPanel("tab1",

column(12,
DT::dataTableOutput("table1")
)),

tabPanel( "tab2",

column(12,
DT::dataTableOutput("table2")
))
)
)
,
tabItem(
tabName = "page2",
fluidRow(
column(12,
DT::dataTableOutput("table3")
))
)
)
)
)

server <- function(input, output) {

# table1
tbl1 <- mtcars[1:30, ] # tables 1, 2, 3 use different rows of mtcars to differentiate tables

output$table1 <- DT::renderDataTable({
datatable( tbl1,
# options = DToptions, # no such object called "DToptions"
extensions = 'Buttons',
rownames = TRUE,
selection = 'none'
)
})


# table2
tbl2 <- mtcars[5:45, ]

output$table2 <- DT::renderDataTable({
datatable( tbl2,
# options = DToptions,
extensions = 'Buttons',
rownames = TRUE,
selection = 'none'
)
})

# table3
tbl3 <- mtcars[11:35, ]

output$table3 <- DT::renderDataTable({
datatable( tbl3,
# options = DToptions,
extensions = 'Buttons',
rownames = TRUE,
selection = 'none'
)
})


page_name <- reactive({
input$pages
})

# select table on the active page / tab
selected_table <- reactive({
if(page_name() == "page1"){
tbl.list <- list("tab1" = tbl1, "tab2" = tbl2)
select_tbl <- tbl.list[input$tabs]
}else{
select_tbl <- tbl3
}
return(select_tbl)
})

# download table
output$downloadData <- downloadHandler(
filename = function() {"table.csv"},
content = function(file) {write.csv(selected_table(), file, row.names=TRUE)}
)
}

shinyApp(ui, server)


Related Topics



Leave a reply



Submit