Restore input values with Shiny URL bookmark and rerun calculations

梦想的初衷 提交于 2020-01-24 00:58:08

问题


So I have a use case for a shiny app where the users can enter some value and when clicked on run it would run a model and show the values in the table. Now when I click on bookmark it captures the input values. And when I click on the restore bookmark it does populate the input values. What I want to do is after it restores the input values it should also run the model again and populate the values in the table. In short restore bookmark should populate the values and click on the run button to run the model.How can this be achieved ?

Below is the code for bookmark :

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

ui <- function(request) {
  fluidPage(
    DT::dataTableOutput("x1"),
    column(
      12,
      column(3,tags$div(title="forecast", numericInput("budget_input", label = ("Total Forecast"), value = 2))),
      column(2, textInput(inputId = "description", label = "Bookmark description", placeholder = "Data Summary")),
      column(2, bookmarkButton(id="bookmarkBtn"))),
    column(2, actionButton("opt_run", "Run")),
    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()
  })

  observeEvent(input$opt_run, {
    output$x1 = renderDT(df %>% mutate(Current  = as.numeric(Current)*(input$budget_input)), selection = 'none', editable = TRUE)
  })

  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"))

  df <- data.table(Channel = c("A", "B","C"),
                   Current = c("2000", "3000","4000"),
                   Modified = c("2500", "3500","3000"),
                   New_Membership = c("450", "650","700"))

  output$x1 = renderDT(df, selection = 'none', editable = TRUE)

  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, User = Sys.getenv("USERNAME")), 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, User = Sys.getenv("USERNAME")))), by="URL")
      }
    }
  })

  output$urlTable = DT::renderDataTable({
    req(myBookmarks$urlDF)
    myBookmarks$urlDF[User %in% Sys.getenv("USERNAME")]
  }, escape=FALSE)

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

回答1:


My first instinct was that you probably need to use onRestore() as @AndrewTaylor suggested. But after trying to run your code, it was evident that the issue here is fixed by simply fixing the reactivity in the code.

Here is your code, with two small edits: first, the output$x1 was defined twice, so I removed the second one that was not using any reactive values. Secondly, I moved the first output$x1 to be outside of an observeEvent, and made it trigger only when the button is pressed. You should generally not define an output inside an observer, unless it's a special case where it's mandatory, but the way it was done here causes incorrect reactivity. Fixing this is all you needed.

Also, the DT and dplyr packages needed to be loaded to make the code fully reproducible.

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

ui <- function(request) {
  fluidPage(
    DT::dataTableOutput("x1"),
    column(
      12,
      column(3,tags$div(title="forecast", numericInput("budget_input", label = ("Total Forecast"), value = 2))),
      column(2, textInput(inputId = "description", label = "Bookmark description", placeholder = "Data Summary")),
      column(2, bookmarkButton(id="bookmarkBtn"))),
    column(2, actionButton("opt_run", "Run")),
    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()
  })

  observeEvent(input$opt_run, {
    cat('HJE')
  })

  output$x1 <- DT::renderDataTable({
    input$opt_run
    isolate({
      datatable(
        df %>% mutate(Current  = as.numeric(Current)*(input$budget_input)), selection = 'none', editable = TRUE
      )
    })
  })

  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"))

  df <- data.table(Channel = c("A", "B","C"),
                   Current = c("2000", "3000","4000"),
                   Modified = c("2500", "3500","3000"),
                   New_Membership = c("450", "650","700"))

  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, User = Sys.getenv("USERNAME")), 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, User = Sys.getenv("USERNAME")))), by="URL")
      }
    }
  })

  output$urlTable = DT::renderDataTable({
    req(myBookmarks$urlDF)
    myBookmarks$urlDF[User %in% Sys.getenv("USERNAME")]
  }, escape=FALSE)

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


来源:https://stackoverflow.com/questions/54831077/restore-input-values-with-shiny-url-bookmark-and-rerun-calculations

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!