Dear R Shiny community,
I am trying to create a bookmarking state for Shiny app where I render table with DT package. For example, in the app pasted below I want to type some text in the search field which subsets data and bookmark that state, i.e. get a URL that I can share. Another user can use the URL and see the same subset of the table without a need to type the text again into the search field. With the code below I was expecting to see the "Bookmark" button with the option 1 code or a dynamic URL with option 2, but unfortunately it does not work as expected. Does anyone know how to make a bookmarking state when rendering a table with DT?
Here is the reproducible code:
Option 1
library(shiny)
ui <- function(request) {
fluidPage(DT::dataTableOutput('tbl'))
}
server = function(input, output) {
output$tbl = DT::renderDataTable(
iris, options = list(lengthChange = FALSE)
)
}
shinyApp(ui, server, enableBookmarking = "url")
Option 2
library(shiny)
ui <- function(request) {
fluidPage(DT::dataTableOutput('tbl'))
}
server = function(input, output) {
observe({
output$tbl = DT::renderDataTable(
iris, options = list(lengthChange = FALSE)
)
})
onBookmarked(function(url) {
updateQueryString(url)
})
}
shinyApp(ui, server, enableBookmarking = "url")
Thank you so much for your time and help!
Based on the following discussion https://groups.google.com/forum/#!topic/shiny-discuss/DvWhqwZ8OKw I was able to find an answer.
I was able to modify the option 1 and here is the minimal reproducible app that works. Just type a string in a global search field, click on the bookmark button on the bottom, copy the url and share.
library(DT)
library(shiny)
ui <- function(request) {
fluidPage(
DT::dataTableOutput('tbl')
, bookmarkButton(label = "Bookmark", title = "Link to this view")
)
}
server = function(input, output) {
# exclude some values query variables from url
setBookmarkExclude(names = c("resTable_rows_all",
"resTable_cell_clicked"))
# proxy for table manipulations
tbl_proxy <- dataTableProxy("tbl")
# restore table selection and search
onRestored(function(state) {
# req(state$input$resTable_search)
DT::updateSearch(tbl_proxy,
keywords = list(global = state$input$tbl_search))
})
output$tbl <- renderDataTable(iris)
}
shinyApp(ui, server, enableBookmarking = "url")
Related
I have a shiny application that lets the user filter data, eventually the user should be able to download the filtered data but I cannot access the filtered/shown data from reactable.
An MWE would be the following: (Note that the getReactableState() function does not return the filtered data but would work if one had to select all filtered data.)
library(shiny)
library(reactable)
ui <- fluidPage(
reactableOutput("table"),
verbatimTextOutput("table_state")
)
server <- function(input, output) {
output$table <- renderReactable({
reactable(iris, filterable = TRUE)
})
output$table_state <- renderPrint({
print(getReactableState("table")) #< wrong code here...
# the goal would be to get the rows which are currently shown here
})
}
shinyApp(ui, server)
Not a full answer, but at least it allows to download the filtered data as a CSV (solution from here):
tags$button("Download as CSV", onclick = "Reactable.downloadDataCSV('table')")
The full solution looks like this:
library(shiny)
library(reactable)
ui <- fluidPage(
tags$button("Download as CSV", onclick = "Reactable.downloadDataCSV('table')"),
reactableOutput("table")
)
server <- function(input, output) {
output$table <- renderReactable({
reactable(iris, filterable = TRUE)
})
}
shinyApp(ui, server)
I'm new to shiny, so don't mind me if my question is simple.
I want to take a path as an input from the user and generate the data frame. I've done this so far:
library(shiny)
ui <- fluidPage(
textInput("data_path", "Please enter the path of your data: ")
tableOutput("data_glimpse")
)
server <- function(input, output){
data <- read.csv(input$data_path)
output$data_glimpse <- renderTable({
glimpse(data)
})
}
shinyApp(ui = ui, server = server)
But it's not working right. I don't get any pages to enter my path!
Any help?
I think it is easier to upload the file directly. But if you want to keep this structure, you can try the following. To make it work you have to add to your path the name of the file plus .csv, e.g. /sample.csv
library(shiny)
ui <- fluidPage(
textInput("data_path", "Please enter the path of your data: "),
tableOutput("data_glimpse")
)
server <- function(input, output){
dataTable <- reactive({
data <- read.csv(input$data_path)
})
output$data_glimpse <- renderTable({
dplyr::glimpse(dataTable())
})
}
shinyApp(ui = ui, server = server)
I'm creating a Shiny app which displays images and text in a data table. This table will need to update depending on the user's input. When I run the app in a window the table updates as expected. However, when I run it in a browser the text updates but the image does not. How do I make it work in a browser?
EDIT: For clarity, the below example is just to reproduce the issue. The real app could display any number of different pictures, which aren't saved locally until the user makes a selection (they're pulled from a database). I was hoping to avoid having different filenames because I could potentially end up with hundreds of thousands of pictures saved locally, but if that's the only solution then I will have to cleanup the folder periodically
Reproducible example (requires 2 local images)
library(shiny)
library(imager)
library(DT)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Tables to export"),
sidebarLayout(
sidebarPanel(
actionButton("pic1","Pic1"),
actionButton("pic2","Pic2")
),
# Show tables
mainPanel(
fluidRow(
dataTableOutput('tab1')
)
)
)
)
# Define server logic
server <- function(input, output) {
observeEvent(input$pic1, {
pic <- load.image("www/pic1.png")
save.image(pic,"www/picToShow.png")
tab1 <- datatable(t(data.frame("Pic"='<img src="picToShow.png" width=150 height=100>',x1=1,x2=2,x3=3,row.names="p1")),
escape = F, options = list(dom = 't',pageLength = 20))
output$tab1 <- renderDataTable(tab1)
})
observeEvent(input$pic2, {
pic <- load.image("www/pic2.png")
save.image(pic,"www/picToShow.png")
tab1 <- datatable(t(data.frame("Pic"='<img src="picToShow.png" width=150 height=100>',x1=4,x2=5,x3=6,row.names="p1")),
escape = F, options = list(dom = 't',pageLength = 20))
output$tab1 <- renderDataTable(tab1)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Expected behaviour (behaviour in window)
Behaviour in the browser
I agree with #MrFlick's comment. Why do you load both images and resave them with the same name? The browser will think that it knows the image already and will re-use the already loaded image.
Why not just include pic1.png and pic2.png directly?
server <- function(input, output) {
observeEvent(input$pic1, {
tab1 <- datatable(t(data.frame("Pic"='<img src="pic1.png" width=150 height=100>',x1=1,x2=2,x3=3,row.names="p1")),
escape = F, options = list(dom = 't',pageLength = 20))
output$tab1 <- renderDataTable(tab1)
})
observeEvent(input$pic2, {
tab1 <- datatable(t(data.frame("Pic"='<img src="pic2.png" width=150 height=100>',x1=4,x2=5,x3=6,row.names="p1")),
escape = F, options = list(dom = 't',pageLength = 20))
output$tab1 <- renderDataTable(tab1)
})
}
library(shiny)
library(imager)
library(DT)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Tables to export"),
sidebarLayout(
sidebarPanel(
actionButton("pic1","Pic1"),
actionButton("pic2","Pic2")
),
# Show tables
mainPanel(
fluidRow(
DT::dataTableOutput('tab1')
)
)
)
)
# Define server logic
server <- function(input, output) {
vals = reactiveValues(pic1 = 0, pic2 = 0)
observeEvent(input$pic1, {
vals$pic1 <- 1
vals$pic2 <- 0
})
observeEvent(input$pic2, {
print(vals$pic1)
print(vals$pic2)
vals$pic1 <- 0
vals$pic2 <- 1
})
dynamicdf <- reactive({
if(vals$pic1 == 1) {
df <- data.frame(
pic = c('<img src="http://flaglane.com/download/american-flag/american-flag-large.png" height="52"></img>'),
x1 = c(1),
x2 = c(2),
x3 = c(3)
)
} else {
df <- data.frame(
pic = c('<img src="img2.jpg" width=150 height=100></img>'),
x1 = c(4),
x2 = c(5),
x3 = c(6)
)
}
print(df)
return(df)
})
output$tab1 <- DT::renderDataTable({
DT::datatable(dynamicdf(), escape = FALSE)
})
}
# Run the application
shinyApp(ui = ui, server = server)
In Shiny Apps you do not load or saves images. You display them by using a path to the folder, where your pictures are stored. This can be a Link on the internet or a path on your machine.
Do it like this. I use a reactiveValue to track the last click of your button. This is a good solution if you have a large number of pictures you may want to render. (I adopted that style from the modern JS Library ReactJS) Based on the state you display your pictures. Do NOT use the www path, this is already expected by shiny. Leave it as in the example2 in the App.
For me it also only worked with the escape = FALSE parameter in the App. Try that if it does not work without it.
I am trying to create a table using Shiny, where the user can click on a row in order to see further information about that row. I thought I understood how to do this (see code attached).
However, right now as soon as the user clicks the "getQueue" action button, the observeEvent(input$fileList_cell_clicked, {}) seems to get called. Why would this be called before the user even has the chance to click on a row? Is it also called when the table is generated? Is there any way around this?
I need to replace "output$devel <- renderText("cell_clicked_called")" with code that will have all sorts of errors if there isn't an actual cell to refer to.
Thank you for any advice!
ui <- fluidPage(
actionButton("getQueue", "Get list of queued files"),
verbatimTextOutput("devel"),
DT::dataTableOutput("fileList")
)
shinyServer <- function(input, output) {
observeEvent(input$getQueue, {
#get list of excel files
toTable <<- data.frame("queueFiles" = list.files("queue/", pattern = "*.xlsx")) #need to catch if there are no files in queue
output$fileList <- DT::renderDataTable({
toTable
}, selection = 'single') #, selection = list(mode = 'single', selected = as.character(1))
})
observeEvent(input$fileList_cell_clicked, {
output$devel <- renderText("cell_clicked_called")
})}
shinyApp(ui = ui, server = shinyServer)
minimal error code
DT initializes input$tableId_cell_clicked as an empty list, which causes observeEvent to trigger since observeEvent only ignores NULL values by default. You can stop the reactive expression when this list is empty by inserting something like req(length(input$tableId_cell_clicked) > 0).
Here's a slightly modified version of your example that demonstrates this.
library(shiny)
ui <- fluidPage(
actionButton("getQueue", "Get list of queued files"),
verbatimTextOutput("devel"),
DT::dataTableOutput("fileList")
)
shinyServer <- function(input, output) {
tbl <- eventReactive(input$getQueue, {
mtcars
})
output$fileList <- DT::renderDataTable({
tbl()
}, selection = 'single')
output$devel <- renderPrint({
req(length(input$fileList_cell_clicked) > 0)
input$fileList_cell_clicked
})
}
shinyApp(ui = ui, server = shinyServer)
I want to insert a hyperlink to DT table in shiny.
To save the loading time, I want to insert hyperlinks to current view (input$table_rows_current).
I have tired with observing but I don't know how to specify where to insert hyperlink and how?
Any help much appreciated.
Here is the sample code:
library(shiny)
createLink <- function(val) {
sprintf('<a href="https://www.google.com/#q=%s" target="_blank" >%s</a>',val,val)
}
ui <- fluidPage(
titlePanel("Table with Links!"),
sidebarLayout(
sidebarPanel(
h4("Click the link in the table to see
a google search for the car.")
),
mainPanel(
dataTableOutput('table1')
)
)
)
server <- function(input, output) {
output$table1 <- renderDataTable({
dt <- datatable(mtcars, escape=FALSE, selection = 'none') %>% formatStyle(0, cursor = 'pointer')
})
observe({
List <- input$table1_rows_current
List <- createLink(List)
return(List)
})
}
shinyApp(ui, server)
The function createLink is not working because you missed one val:
Corrected:
createLink <- function(val,val) {
sprintf('<a href="https://www.google.com/#q=%s' target="_blank" >%s</a>',val,val)
}
Then you can use createLink() as below:
input$table1_rows_current = createLink(input$table1_rows_current,
input$table1_rows_current)
It will show you embedded link column.