【问题标题】:Modal opens up only once on button click in R Datatable shiny app在 R Datatable 闪亮的应用程序中单击按钮时,模态仅打开一次
【发布时间】:2019-08-04 15:29:50
【问题描述】:

我有一个保存书签 URL 的表。截至目前,当您单击按钮时,它会打开模式。但是,一旦您拥有第二条记录并单击该按钮,它就不会打开模式。此外,当模式打开时,它有一个 href。如何清理它并只显示 URL?

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



ui <- function(request) {
  fluidPage(rclipboardSetup(),
    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"))


  shinyInput <- function(FUN, len, id, ...) {
    inputs <- character(len)
    for (i in seq_len(len)) {
      inputs[i] <- as.character(FUN(paste0(id, i), ...))
    }
    inputs
  }

  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>"),
              Share = shinyInput(actionButton, 10, 'button_', label = "Assessment", onclick = 'Shiny.onInputChange(\"select_button\",  this.id)' ),
              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>"),
              Share = shinyInput(actionButton, 10, 'button_', label = "Assessment", onclick = 'Shiny.onInputChange(\"select_button\",  this.id)' ),
              Timestamp = Sys.time(),
              Session = session$token,
              User = Sys.getenv("USERNAME")
            )
          )), by = "URL")
      }
    }
  })
  observeEvent(input$select_button, {
  showModal(urlModal(
   myBookmarks$urlDF[input$urlTable_rows_selected,URL],
    title = "You have selected a row!"
  ))
  })

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

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

【问题讨论】:

  • rclipboard 可能感兴趣。
  • @ismirsehregal 我试过了,但没有运气。修改了上面的例子。
  • 我再次更新了我的答案setBookmarkExclude 现在可以正常工作了。

标签: r datatable shiny


【解决方案1】:

这就是我认为你所追求的:

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

ui <- function(request) {
  fluidPage(
    useShinyjs(),
    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')
  })

  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 <- DT::renderDataTable({
    input$opt_run
    req(input$budget_input)
    isolate({
      datatable(
        df %>% mutate(Current  = as.numeric(Current)*(input$budget_input)), selection = 'none', editable = TRUE
      )
    })
  }, server = FALSE)

  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
  }

  observe({
    toExclude <- c("bookmarkBtn", "description", "urlTable_cell_clicked", "urlTable_rows_all", "urlTable_rows_current", "urlTable_rows_selected", "urlTable_search", "urlTable_state", "urlTable_row_last_clicked")

    if(!is.null(myBookmarks$urlDF)){
      shareBtnExclude <- paste0("shareBtn", seq_len(nrow(myBookmarks$urlDF)))
      toExclude <- c(toExclude, shareBtnExclude)
    }

    delayExclude <- grep("delay", names(input), value = TRUE)
    if(length(delayExclude) > 0){
      toExclude <- c(toExclude, delayExclude)
    }

    setBookmarkExclude(toExclude)
  })

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

  onBookmarked(fun=function(url){
    if(!url %in% myBookmarks$urlDF$Link){
      if(is.null(myBookmarks$urlDF)){
        myBookmarks$urlDF <-
          unique(
            data.table(
              Description = input$description,
              Link = paste0("<a href='", url, "'>", url, "</a>"),
              Share = as.character(actionButton(inputId=paste0("shareBtn", 1), label = "Assessment", onclick = sprintf('Shiny.setInputValue("shareBtn1", "%s", {priority: "event"});', url))),
              Timestamp = Sys.time(),
              Session = session$token,
              User = Sys.getenv("USERNAME")
            ),
            by = "Link"
          )
      } else {
        myBookmarks$urlDF <-
          unique(rbindlist(list(
            myBookmarks$urlDF,
            data.table(
              Description = input$description,
              Link = paste0("<a href='", url, "'>", url, "</a>"),
              Share = as.character(actionButton(inputId=paste0("shareBtn", nrow(myBookmarks$urlDF)+1), label = "Assessment", onclick = sprintf('Shiny.setInputValue("%s", "%s", {priority: "event"});', paste0("shareBtn", nrow(myBookmarks$urlDF)+1), url))),
              Timestamp = Sys.time(),
              Session = session$token,
              User = Sys.getenv("USERNAME")
            )
          )), by = "Link")
      }
    }
  })

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

  observeEvent(lapply(paste0("shareBtn", seq_len(nrow(req(myBookmarks$urlDF)))), function(x) input[[x]]), {
    req(myBookmarks$urlDF)
    delay(100, {req(input[[paste0("shareBtn", input$urlTable_cell_clicked$row)]])
      showModal(urlModal(
        input[[paste0("shareBtn", input$urlTable_cell_clicked$row)]],
        title = paste("You have selected row", input$urlTable_cell_clicked$row)
      ))}
    )
  }, ignoreInit = TRUE)

}

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

我将您的电话挂断至shinyInput,您要求该函数每行创建 10 个操作按钮。我还更改了onclick 参数以直接传递url。

老实说,我不认为将这些按钮添加到每个数据表行是一个好的选择,因为您必须跟踪动态生成的输入,这些输入要通过 setBookmarkExclude 从书签中排除(这不是似乎工作得很好)。

编辑:将排除部分放在单独的 observer 中,而不是 onBookmark 函数似乎可以解决这个问题。

尽管如此,this 对于创建由动态创建的按钮触发的观察者非常有帮助。

点击链接后直接将网址复制到剪贴板的解决方案会更优雅,但应该在另一个问题中解决。

【讨论】:

    猜你喜欢
    • 2017-07-10
    • 1970-01-01
    • 2021-12-28
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多