4

I am trying save the bookmark URL from the shiny app into a table so if the user clicks on a saved URL to retrieve the bookmarked state of the app. When you click on the bookmark button you get a URL how can that be inserted into a table. When saved in a table a view button with each saved bookmark will allow the user to view the saved bookmark state.

 ui <- function(request) {
  fluidPage(
    plotOutput("plot"),
    sliderInput("n", "Number of observations", 1, nrow(faithful), 100),
    bookmarkButton()
  )
}

server <- function(input, output, session) {
  output$plot <- renderPlot({
    hist(faithful$eruptions[seq_len(input$n)], breaks = 40)
  })
}

enableBookmarking(store = "url")
shinyApp(ui, server)
SNT
  • 1,283
  • 3
  • 32
  • 78

1 Answers1

4

Here is how I would approach this:

Edit: Now using sqlite to persist the changes across different session, also duplicates are avoided.

2nd Edit: Added a description input for the bookmarks.

library(shiny)
library(RSQLite)
library(data.table)

ui <- function(request) {
  fluidPage(
    plotOutput("plot"),
    sliderInput("n", "Number of observations", 1, nrow(faithful), 100),
      fluidRow(column(2, textInput(inputId = "description", label = "Bookmark description", placeholder = "Data Summary")), column(2, bookmarkButton(id="bookmarkBtn"))),
      DT::dataTableOutput("urlTable", width = "100%"),
    tags$style(type='text/css', "#bookmarkBtn { width:100%; margin-top: 25px;}")
  )
}

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

  con <- dbConnect(RSQLite::SQLite(), "bookmarks.db", overwrite = FALSE)
  myBookmarks <- reactiveValues(urlDF = NULL)

  observeEvent(input$bookmarkBtn, {
    session$doBookmark()
  })

  if(dbExistsTable(con, "Bookmarks")){
    tmpUrlDF <- data.table(dbReadTable(con, "Bookmarks"))
    myBookmarks$urlDF <- tmpUrlDF[, Timestamp := as.POSIXct(Timestamp, origin="1970-01-01 00:00")]
  } else {
    myBookmarks$urlDF <- NULL
  }

  session$onSessionEnded(function() {
    tmpUrlDF <- isolate({myBookmarks$urlDF})
    if(!is.null(tmpUrlDF)){
      dbWriteTable(con, "Bookmarks", tmpUrlDF, overwrite = TRUE)
    }
    dbDisconnect(con)
  })

  setBookmarkExclude(c("bookmarkBtn", "description", "urlTable_cell_clicked", "urlTable_rows_all", "urlTable_rows_current", "urlTable_rows_selected", "urlTable_search", "urlTable_state", "urlTable_row_last_clicked"))

  output$plot <- renderPlot({
    hist(faithful$eruptions[seq_len(input$n)], breaks = 40)
  })

  onBookmarked(fun=function(url){
    if(!url %in% myBookmarks$urlDF$URL){
      if(is.null(myBookmarks$urlDF)){
        myBookmarks$urlDF <- unique(data.table(Description = input$description, URL = paste0("<a href='", url, "'>", url,"</a>"), Timestamp = Sys.time(), Session = session$token), by="URL")
      } else {
        myBookmarks$urlDF <- unique(rbindlist(list(myBookmarks$urlDF, data.table(Description = input$description, URL = paste0("<a href='", url, "'>", url,"</a>"), Timestamp = Sys.time(), Session = session$token))), by="URL")
      }
    }
  })

  output$urlTable = DT::renderDataTable({
    myBookmarks$urlDF
  }, escape=FALSE)

}

enableBookmarking(store = "url")
shinyApp(ui, server)

You might want to think about saving the bookmark table to a file (e.g. using saveRDS()) and load it globally so its available for new sessions. For further information see this.

ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
  • Thanks a lot. Just a couple of questions. This table can be inserted into a db . And secondly when I click on any bookmark the table disappears. – SNT Dec 20 '18 at 16:51
  • Sure the table can be saved in a DB (I'll add a sqlite example when I have the time - actually that was why I mentioned saving a file globally). The table disappears because when clicking the link a new session is started (try rightclick -> open in a new tab). – ismirsehregal Dec 20 '18 at 16:58
  • Thank you. And along with the bookmark URL can I replace the URL with some kind of name so that it would be easy for the user to retrieve by name rather than the URL – SNT Dec 20 '18 at 17:00
  • Sure thats possible too. Just replace the second `unlist(myBookmarks$url)` in the href-paste (sorry currently on mobile so I can't edit properly). – ismirsehregal Dec 20 '18 at 17:04
  • So I did add the text input as you can see I modified your answer. It takes the same name for all bookmarks now. – SNT Dec 20 '18 at 20:34
  • Your edit was rejected (not by me), I think those suggested changes are something to write here in the comments. I updated my answer to persist the bookmarks among multiple sessions using sqlite – please check. – ismirsehregal Dec 21 '18 at 10:30
  • I added this `textInput("caption", "Caption", "Data Summary")` and `{ input$caption }` which lead to the same name for all bookmarks – SNT Dec 21 '18 at 14:03
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/185614/discussion-between-snt-and-ismirsehregal). – SNT Dec 21 '18 at 14:04
  • Can I use this with `URL` bookmarking in Shinyapp.io . And can this be saved without using a db – SNT Jan 29 '19 at 20:19
  • You can save the table of bookmarks using `saveRDS()` instead of saving it to a db (as mentioned above already). I have no experience regarding bookmarks on shinyapps.io.. just give it a try. – ismirsehregal Jan 29 '19 at 20:26
  • I added this `saveRDS(myBookmarks$urlDF, "bookmark.rds")` but it didnt seem to be working – SNT Jan 29 '19 at 20:30
  • I can start it as a new question. What I want to try is save these bookmarks using `saveRDS`/`write_RDS` and when I start the app again it should load the saved bookmarks – SNT Jan 29 '19 at 20:46
  • Sure, that's possible. Sorry currently only on mobile. – ismirsehregal Jan 29 '19 at 21:20
  • I have created a new question for it here https://stackoverflow.com/questions/54426953/bookmarking-and-saving-the-bookmarks-in-r-shiny – SNT Jan 29 '19 at 21:26