Is there a built in Shiny attribute that counts the number of times a downloadButton is clicked? I'm not finding it in the function help or web searches. If there's not a built in method how would I go about counting the clicks. Here's a working example:
data <- matrix(1:20, nrow=5)
ui <- fluidPage(title = 'Count Button Clicks',
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 =','what variable goes here?')
})
output$dwnldBtn <- downloadHandler(
filename = 'data.csv',
content = function(file){
write.csv(data, file)
},
contentType = 'csv'
)
}
shinyApp(ui = ui, server = server)
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)
Related
Is there a way to trigger the tab only when the user clicks on action button . Example shown below. So tab2 is hidden, but when the user clicks on action button, the tab should pop up
library(shiny)
ui <- fluidPage(
tabsetPanel(id = "tabs",
tabPanel(value = "tab1", title = "Tab 1",
tableOutput("myTable"),
actionButton("sub","Submit")
),
uiOutput("show_tab1")
# tabPanel(value = "tab2", title = "Tab 2",
# plotOutput("myPlot")
# )
)
)
server <- function(input, output, session) {
observeEvent(input$sub,{
output$show_tab1 <- renderUI({
tabPanel(value = "tab2", title = "Tab 2",
plotOutput("myPlot")
)
})
})
}
shinyApp(ui, server)
Maybe this:
library(shiny)
ui <- fluidPage(
tabsetPanel(id = "tabs",
tabPanel(value = "tab1", title = "Tab 1",
tableOutput("myTable"),
actionButton("sub","Submit")
),
tabPanel(value = "tab2", title = "Tab 2",plotOutput("myPlot"))
)
)
server <- function(input, output, session) {
observe({
hideTab(inputId = "tabs", target = "tab2")
})
observeEvent(input$sub,{
showTab(inputId = "tabs", target = "tab2")
})
}
shinyApp(ui, server)
In the below application, the edit works fine for the first time. (Say you click on first row button, it works fine. But once you cancel and again click on same button, it is not working)
Can anyone help me here? Is it related to binding ?
library(shiny)
ui <- fluidPage(
dataTableOutput("df")
)
server <- function(input, output, session) {
shinyInput <- function(FUN, len, id, ...) {
inputs <- character(len)
for (i in seq_len(len)) {
inputs[i] <- as.character(FUN(paste0(id, i), ...))
}
inputs
}
output$df <- renderDataTable({
iris$Edit = shinyInput(actionButton, nrow(iris), 'button_', label = "Edit", onclick = 'Shiny.onInputChange(\"select_button\", this.id)' )
datatable(iris, escape = F)
})
observeEvent(input$select_button,{
selectedRow <- as.numeric(strsplit(input$select_button, "_")[[1]][2])
showModal(modalDialog(
title = "Edit", size = "l",
fluidPage(width = 12,fluidRow(
column(width = 3,selectedRow)
)),
footer = tagList(modalButton("Cancel"),actionButton("update", "Update"))))
})
}
shinyApp(ui, server)
You should change this.id on this.id + "_" + Date.now()
When you generate unique this.id it works properly.
I am looking for a code snippet using which, I can enable/disable sidebar toggle button in shinydashboard header.
library(shiny)
library(shinydashboard)
library(shinyjs)
ui <- shinyUI(dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
useShinyjs()
)
))
server <- shinyServer(function(input, output, session) {
addClass(selector = "body", class = "sidebar-collapse") # Hide Side Bar
})
shinyApp(ui = ui, server = server)
Let me know if anybody can help???
If you use the shinyjs package, you can show or hide the sidebar toggle with a quick line of JavaScript.
library(shiny)
library(shinydashboard)
library(shinyjs)
ui <- shinyUI(dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
useShinyjs(),
actionButton("hide","Hide toggle"),
actionButton("show","Show toggle")
)
))
server <- shinyServer(function(input, output, session) {
observeEvent(input$hide,{
shinyjs::runjs("document.getElementsByClassName('sidebar-toggle')[0].style.visibility = 'hidden';")
})
observeEvent(input$show,{
shinyjs::runjs("document.getElementsByClassName('sidebar-toggle')[0].style.visibility = 'visible';")
})
})
shinyApp(ui = ui, server = server)
The JavaScript itself just refers to the first element with class sidebar-toggle (i.e. the menu button), and toggles the visibility depending on which button the user presses.
I have found a solution to this...If someone is stuck with same problem, can refer to below solution:
library(shiny)
library(shinydashboard)
library(shinyjs)
ui <- shinyUI(dashboardPage(
dashboardHeader(),
dashboardSidebar( tags$head(
tags$script(
HTML(#code for hiding sidebar tabs
"Shiny.addCustomMessageHandler('manipulateMenuItem1', function(message)
{
var aNodeList = document.getElementsByTagName('a');
for (var i = 0; i < aNodeList.length; i++)
{
if(aNodeList[i].getAttribute('data-toggle') == message.toggle && aNodeList[i].getAttribute('role') == message.role)
{
if(message.action == 'hide')
{
aNodeList[i].setAttribute('style', 'display: none;');
}
else
{
aNodeList[i].setAttribute('style', 'display: block;');
};
};
}
});"
)
)
)
),
dashboardBody(
useShinyjs(),
actionButton("h1","Hide toggle"),
actionButton("h2","Show toggle")
)
))
server <- shinyServer(function(input, output, session) {
observeEvent(input$h1,{
session$sendCustomMessage(type = "manipulateMenuItem1", message = list(action = "hide",toggle = "offcanvas", role = "button"))
})
observeEvent(input$h2,{
session$sendCustomMessage(type = "manipulateMenuItem1", message = list(action = "show",toggle = "offcanvas", role = "button"))
})
})
shinyApp(ui = ui, server = server)
I have created a shiny app to save start time and and end time when I click these buttons. I have three buttons: Start, End and Download, this app is intended to save the time when I have clicked Start and End buttons and then save the file in .csv when I click Download button. But it is saving the time of Download button click. Please help me save the different time properly.
library(shiny)
shinyUI(fluidPage(
titlePanel("Header"),
sidebarLayout(
sidebarPanel(
actionButton("start", "Start"),
tags$br(),
actionButton("end", "End"),
tags$br(),
downloadButton("downloadData", "Download")
),
mainPanel(
)
)
))
shinyServer(function(input, output) {
startTime <- eventReactive(input$start,{
Sys.time()
})
endTime <- eventReactive(input$end,{
Sys.time()
})
data <- reactive({data.frame(start = startTime(),
end = endTime())})
output$downloadData <- downloadHandler(
filename = function() {
"download.csv"
},
content = function(file) {
write.csv(data(), file, row.names = F)
}
)
})
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)
I working on a project where I have to create a form in shiny. I currently have a datatable in the UI which has email in the form of hyperlink. Once the hyperlink is clicked the modal window opens where I have another UI which shows the various fields to be filled. I have a save button here that should update my DB in the backend once the button is clicked.
The problem I am facing is that I am unable to reference each email to that particular modal window and my update query updates all the records in the DB. Is there a way to pass all the record details that has been clicked into the modal window??
What I basically need to know is how to update the record that I have clicked on and for which the pop up window is opened??
I am attaching the UI.R and server.R for use.
enter code here
ui.R
library(shiny)
library(DT)
library(shinyBS)
fluidPage(
fluidRow(
actionButton(inputId = "view",label = "Hi")),
#actionButton(inputId = "savepage1", label = "Save"),
DT::dataTableOutput('my_table'),
bsModal("FormModal", "My Modal", "",textOutput('mytext'),uiOutput("form1"),
actionButton("savepage2","Save"),DT::dataTableOutput("table1"),size = "large")
)
enter code here
server.R
library(shinyBS)
server <- function(session, input, output){
uedata<-c("","Prime","Optimus") ##add source data here
output$form1<-renderUI({
tagList(
column(width=6,selectInput("samplevalue","Select Custom Source*",choices=c("Please select",samplevaluedata))),
column(width=6,textInput("sampletext",label = "Enter Text",value = NULL,placeholder = NULL)))
})
on_click_js = "Shiny.onInputChange('mydata', '%s');
$('#FormModal').modal('show')"
convert_to_link = function(x) {
as.character(tags$a(href = "#", onclick = sprintf(on_click_js,x), x))
}
observeEvent(input$view,{
session$sendCustomMessage(type = "unbinding_table_elements", "my_table")
output$my_table <- DT::renderDataTable({
a=dbGetQuery(hcltcprod,paste0("select name,mobile,email,assignedto from public.tempnew order by 3;"))
a <- data.frame(a,row.names = NULL)
a$email <- sapply(a$email,convert_to_link)
a1 <- datatable(a,
escape = F,
options = list(paging = FALSE, ordering = FALSE, searching = FALSE, rownames = FALSE,
preDrawCallback = JS('function() { Shiny.unbindAll(this.api().table().node());}'),
drawCallback = JS('function() { Shiny.bindAll(this.api().table().node()); } ')))
a1
})
})
observeEvent(input$my_table_cell_clicked, {
print(Sys.time())
})
observe({
if(input$savepage2==0)
return()
isolate({
for(i in 1:nrow(a))
dbGetQuery(hcltcprod,paste0("update public.tempnew set s_text='",input$samplevalue,"',s_value='",input$sampletext,"' where mobile in ('",a$email,"');"))
})
})
}
As your example is connected to database and you didnt provide sample data I will go with mtcars dataset. Building on the example in the link you can view the selected data using the following:
rm(list = ls())
library(DT)
library(shiny)
library(shinyBS)
library(shinyjs)
library(shinydashboard)
# This function will create the buttons for the datatable, they will be unique
shinyInput <- function(FUN, len, id, ...) {inputs <- character(len)
for (i in seq_len(len)) {
inputs[i] <- as.character(FUN(paste0(id, i), ...))}
inputs
}
ui <- dashboardPage(
dashboardHeader(title = "Simple App"),
dashboardSidebar(
sidebarMenu(id = "tabs",
menuItem("Menu Item 1", tabName = "one", icon = icon("dashboard"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "one",h2("Datatable Modal Popup"),
DT::dataTableOutput('my_table'),uiOutput("popup")
)
)
)
)
server <- function(input, output, session) {
my_data <- reactive({
testdata <- mtcars
as.data.frame(cbind(View = shinyInput(actionButton, nrow(testdata),'button_', label = "View", onclick = 'Shiny.onInputChange(\"select_button\", this.id)' ),testdata))
})
output$my_table <- DT::renderDataTable(my_data(),selection = 'single',options = list(searching = FALSE,pageLength = 10),server = FALSE, escape = FALSE,rownames= FALSE)
# Here I created a reactive to save which row was clicked which can be stored for further analysis
SelectedRow <- eventReactive(input$select_button,{
as.numeric(strsplit(input$select_button, "_")[[1]][2])
})
# This is needed so that the button is clicked once for modal to show, a bug reported here
# https://github.com/ebailey78/shinyBS/issues/57
observeEvent(input$select_button, {
toggleModal(session, "modalExample", "open")
})
DataRow <- eventReactive(input$select_button,{
my_data()[SelectedRow(),2:ncol(my_data())]
})
output$popup <- renderUI({
bsModal("modalExample", paste0("Data for Row Number: ",SelectedRow()), "", size = "large",
column(12,
DT::renderDataTable(DataRow())
)
)
})
}
shinyApp(ui, server)