I have a google form/survey that saves the responses into a google sheet.
Data from the google sheet is going into my flexdashboard/shiny app but if a response is saved while someone is using the app - the only way to see the response is by actually clicking refresh in the browser.
I would like to add a button that can rerun the application without the user clicking refresh? Is this possible?
Here is some code I have written - I have some code that I put together but it doesn't seem to work.
---
title: "Test "
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(DT)
library(gsheet)
```
Inputs {.sidebar data-width=300}
-----------------------------------------------------------------------
```{r}
jscode <- "shinyjs.refresh = function() { history.go(0); }"
actionButton(jscode, "Refresh")
observeEvent(input$reset, {
})
```
Column
-------------------------------------
### Chart A
```{r}
data <- gsheet2tbl('https://docs.google.com/spreadsheets/d/1CB2IQHb3g5d8KsEr-_lJNXPKnTBn2nhz_-AzBjRyRK4/edit#gid=0')
datatable(data
,
editable = TRUE,
options = list(
columnDefs = list(list(className = 'dt-center', targets = "_all")))
)
```
We can use invalidateLater(10000) to fetch the data every 10 seconds if the reset button is not preferred.
app:
library(shiny)
library(shinyjs)
library(DT)
library(gsheet)
ui <- fluidPage(
useShinyjs(),
actionButton("reset", inputId = "Refresh"),
DTOutput("table")
)
server <- function(input, output, session) {
observeEvent(input$Refresh, {
refresh()
})
data <- reactive({
#invalidateLater(10000)
gsheet2tbl("https://docs.google.com/spreadsheets/d/1CB2IQHb3g5d8KsEr-_lJNXPKnTBn2nhz_-AzBjRyRK4/edit#gid=0")
})
output$table <- renderDataTable({
datatable(data(),
editable = TRUE,
options = list(
columnDefs = list(list(className = "dt-center", targets = "_all"))
)
)
})
}
shinyApp(ui, server)
A third alternative is to directly re-render the data when the button is pressed:
code:
library(shiny)
library(shinyjs)
library(DT)
library(gsheet)
data <- gsheet2tbl("https://docs.google.com/spreadsheets/d/1CB2IQHb3g5d8KsEr-_lJNXPKnTBn2nhz_-AzBjRyRK4/edit#gid=0")
ui <- fluidPage(
useShinyjs(),
actionButton("reset", inputId = "Refresh"),
DTOutput("table")
)
server <- function(input, output, session) {
observeEvent(input$Refresh, {
df <- gsheet2tbl("https://docs.google.com/spreadsheets/d/1CB2IQHb3g5d8KsEr-_lJNXPKnTBn2nhz_-AzBjRyRK4/edit#gid=0")
output$table <- renderDT({
datatable(df,
editable = TRUE,
options = list(
columnDefs = list(list(className = "dt-center", targets = "_all"))
)
)})
})
#this will render once at the start of the app
output$table <- renderDataTable({
datatable(data,
editable = TRUE,
options = list(
columnDefs = list(list(className = "dt-center", targets = "_all"))
)
)
})
}
shinyApp(ui, server)
Related
I am using DT::datatable() in an R Shiny app to render a table with the header and first column fixed. My app has multiple tabs. I've tried two different approaches but both have bugs that make them unusable. I'm aware that these issues have been reported but I was wondering if anyone knows a workaround that would work in my case.
Approach # 1: scrollY
Here I set scrollY = "500px" in options. The problem is that when I change the number of entries to something other than 10, when I scroll to the bottom, the first column is misaligned with the other columns.
require(shiny)
require(DT)
shinyApp(
ui = tabsetPanel(
tabPanel(
title = "Tab 1",
fluidPage(
DTOutput("table1")
)
),
tabPanel(
title = "Tab 2",
fluidPage(
plotOutput("myPlot"),
DTOutput("table2")
)
)
),
server = function(input, output, session) {
output$table1 <- DT::renderDataTable({
myData <- cbind(iris, iris, iris, iris)
colnames(myData) <- paste0("Column ", 1:ncol(myData))
DT::datatable(
data = myData,
extensions = "FixedColumns",
rownames = F,
options = list(
scrollX = T,
scrollY = "500px",
fixedColumns = list(leftColumns = 1)
)
)
})
output$myPlot <- renderPlot({
plot(1:10, 1:10)
})
output$table2 <- DT::renderDataTable({
DT::datatable(iris)
})
}
)
Approach # 2: FixedHeader extension
Here I use the FixedHeader extension and set fixedHeader = T in options. This avoids the issue with approach # 1, but it has a more serious issue. The fixed header from the table appears on other tabs. In this example, if I scroll down the table on Tab 1, the headers remain fixed as expected, but when I switch to Tab 2 and scroll down, the fixed headers from the table on Tab 1 appear on Tab 2.
require(shiny)
require(DT)
shinyApp(
ui = tabsetPanel(
tabPanel(
title = "Tab 1",
fluidPage(
DTOutput("table1")
)
),
tabPanel(
title = "Tab 2",
fluidPage(
plotOutput("myPlot"),
DTOutput("table2")
)
)
),
server = function(input, output, session) {
output$table1 <- DT::renderDataTable({
myData <- cbind(iris, iris, iris, iris)
colnames(myData) <- paste0("Column ", 1:ncol(myData))
DT::datatable(
data = myData,
extensions = c("FixedColumns", "FixedHeader"),
rownames = F,
options = list(
scrollX = T,
fixedHeader = T,
fixedColumns = list(leftColumns = 1)
)
)
})
output$myPlot <- renderPlot({
plot(1:10, 1:10)
})
output$table2 <- DT::renderDataTable({
DT::datatable(iris)
})
}
)
Updating DT from version 0.19 to version 0.20 (released 11/15/2021) fixed the issue so approach #1 works correctly.
IS there a way to get datatable when the user clicks on the row. Basically when the user clicks on any row, the last 4 columns of that specific row should be displayed in a modal (in datatable format)
library(shiny)
ui <- fluidPage(
DT::dataTableOutput("mydatatable")
)
server <- function(input, output, session) {
mycars = head(mtcars)
output$mydatatable = DT::renderDataTable(mycars, selection = 'single',
rownames = FALSE, options = list(dom = 't'))
observeEvent(input$mydatatable_rows_selected,
{
showModal(modalDialog(
title = "You have selected a row!",
mycars[input$mydatatable_rows_selected,]
))
})
}
shinyApp(ui, server)
You can use renderDataTable inside modalDialog.
library(shiny)
library(DT)
ui <- fluidPage(
DT::dataTableOutput("mydatatable")
)
server <- function(input, output, session) {
mycars = head(mtcars)
output$mydatatable = DT::renderDataTable(mycars, selection = 'single',
rownames = FALSE, options = list(dom = 't'))
observeEvent(input$mydatatable_rows_selected,
{
showModal(modalDialog(
title = "You have selected a row!",
DT::renderDataTable({
DT::datatable(mycars[input$mydatatable_rows_selected, (ncol(mycars) - 3):ncol(mycars)])
})
))
})
}
shinyApp(ui, server)
Given following shiny app:
library(shiny)
library(tidyverse)
library(DT)
ui <- fluidPage(
br(),
DTOutput("DT")
)
server <- function(input, output) {
output$DT <- renderDataTable({
mtcars %>%
datatable(.,extensions = 'Buttons',
options = list(dom = 'Bfrtip',
exportOptions = list(header = ""),
buttons = c('copy', 'csv', 'excel', 'pdf')))
})
}
shinyApp(ui = ui, server = server)
one can copy the full table in the clipboard using the buttons on the top left of the datatable.
But when pasting the content into excel, notepad, or whatever there is a header, which I want to remove.
I'm pretty sure that the header can be deleted or changed using sth. similar to exportOptions = list(header = ""),. But not suprisingly this is not working. Perhaps one can find or translate a solution from here to R/Shiny.
That's the title option of the button:
library(shiny)
library(DT)
ui <- fluidPage(
br(),
DTOutput("DT")
)
server <- function(input, output) {
output$DT <- renderDT({
mtcars %>%
datatable(., extensions = 'Buttons',
options = list(
dom = 'Bfrtip',
buttons = list(
list(
extend = "copy",
text = "COPY",
title = NULL
)
)
)
)
})
}
shinyApp(ui = ui, server = server)
I have a datatable in shiny. When a user selects a certain row, I want to display some other data based on the selected row in a new window. I tried to use shinyBS package but I could not use it without action button and I don't want to include action button. I want the pop up to display when a row is selected. Any ideas?
mymtcars = head(mtcars)
for_pop_up = 1:6
app <- shinyApp(
ui = fluidPage(
DT::dataTableOutput("mydatatable")
),
server = shinyServer(function(input, output, session) {
mycars = head(mtcars)
output$mydatatable = DT::renderDataTable(mycars, selection = 'single',
rownames = FALSE, options = list(dom = 't'))
output$popup = renderPrint({
for_pop_up[input$mydatatable_rows_selected]
})
})
)
runApp(app)
You could use an observeEvent and a modal dialog, like this:
mymtcars = head(mtcars)
for_pop_up = 1:6
app <- shinyApp(
ui = fluidPage(
DT::dataTableOutput("mydatatable")
),
server = shinyServer(function(input, output, session) {
mycars = head(mtcars)
output$mydatatable = DT::renderDataTable(mycars, selection = 'single',
rownames = FALSE, options = list(dom = 't'))
observeEvent(input$mydatatable_rows_selected,
{
showModal(modalDialog(
title = "You have selected a row!",
mycars[input$mydatatable_rows_selected,]
))
})
})
)
Hope this helps!
When using the FixedColumns extension in DT, the rows_selected doesn't register any selections in Sepel.Length
Please see the below example...
Any suggestions on how to get around this would be appreciated.
library(DT)
library(shiny)
ui=shinyUI(
fluidPage(
DT::dataTableOutput("x3")
)
)
server=shinyServer(function(input, output) {
output$x3 = DT::renderDataTable(
DT:::datatable(
iris, rownames=FALSE,
extensions = c('FixedColumns'),
options = list(
fixedColumns = list(leftColumns = 1),
scrollX = TRUE)
))
observe({
s = input$x3_rows_selected
print(s)
})
})
shinyApp(ui=ui,server=server)