【问题标题】:Restore input values with Shiny URL bookmark and rerun calculations使用闪亮的 URL 书签恢复输入值并重新运行计算
【发布时间】:2019-02-22 16:13:40
【问题描述】:

所以我有一个闪亮应用程序的用例,用户可以在其中输入一些值,当点击运行时,它会运行一个模型并在表中显示值。现在,当我单击书签时,它会捕获输入值。当我点击恢复书签时,它会填充输入值。我想要做的是在它恢复输入值之后,它还应该再次运行模型并填充表中的值。简而言之,恢复书签应该填充值并单击运行按钮以运行模型。如何实现?

以下是书签的代码:

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)

【问题讨论】:

标签: r shiny


【解决方案1】:

我的第一直觉是,您可能需要按照@AndrewTaylor 的建议使用onRestore()。但是在尝试运行您的代码之后,很明显,这里的问题是通过简单地修复代码中的反应性来解决的。

这是您的代码,有两个小的修改:首先,输出$x1 被定义了两次,所以我删除了第二个没有使用任何反应值的代码。其次,我将第一个 output$x1 移到了一个 observeEvent 之外,并使它仅在按下按钮时触发。您通常不应该在观察者内部定义输出,除非它是强制性的特殊情况,但这里的完成方式会导致不正确的反应。解决这个问题就是您所需要的。

此外,需要加载 DTdplyr 包以使代码完全可重现。

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)

【讨论】:

  • 哦,我忘了说,这也解决了您可能已经注意到的问题,即在第一次按下运行后甚至没有按下运行按钮的情况下,表格就会不断更新。正确的反应非常重要,否则你会遇到各种奇怪的问题!
  • 这只是一个可重现的示例,但在我正在开发的应用程序中,我有一个模块用于运行模型并呈现输出表 x1。如何在不同的模块中使用同一张表来保存和恢复书签?
  • 不看例子就很难回答你的问题。您的示例没有您提到的问题,因为它是通过解决反应性解决的。如果您的实际应用无法通过这种方式解决,那么我建议您发布一个新问题或编辑您的帖子,以包含一个最小但可重现的示例,在该示例中,通过适当的反应,您的问题仍然会发生
  • 我发现我需要一个最低限度的可重现示例。谢谢 :)
  • 我刚刚在这里添加了一个新问题stackoverflow.com/questions/54835717/…
猜你喜欢
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 2019-06-07
  • 2021-10-25
  • 2021-01-03
相关资源
最近更新 更多