如何从可反应中的单元格呈现按钮触发带有observeEvent的modalBox?

Posted

技术标签:

【中文标题】如何从可反应中的单元格呈现按钮触发带有observeEvent的modalBox?【英文标题】:How to trigger a modalBox with observeEvent from a cell rendered button in a reactable? 【发布时间】:2021-12-04 03:48:12 【问题描述】:

继this 的帖子之后,我想知道为什么当我单击单元格呈现按钮时,observeEvent() 内部的showModal() 不会被触发? 我给按钮observeEvent() 应该听的固定ID“字符”,然后打开模式框。但它没有。

如果我在 ShinyApp UI 中放置一个按钮,observeEvent() 会对 inputid 做出反应,或者如果我将它放置在一个可反应的地方,有什么区别?

library(shiny)
library(reactable)
library(tidyverse)

data = dplyr::starwars %>%
  select(name, height, mass, sex, species, homeworld)

ui = fluidPage(
  
  column(width = 6, style = "margin-top: 50px;",
  reactableOutput("table"))
  
)

server = function(input, output, session)

  
  output$table = renderReactable(
    reactable(data = data,
              height = 600,
              defaultPageSize = 20,
              columns = list(
                name = colDef(
                  cell = function(value)
                    div(htmltools::tags$button(value, class = "action-button", id = "character"))
                  ))))
  
  observeEvent(input$character, 
  showModal(modalDialog(title = "Test"))
  )


shinyApp(ui, server)

【问题讨论】:

【参考方案1】:

reactable 包提供了许多如何使用它的示例,包括每行中的 custom action。该示例有一个“详细信息”列,它显示了看起来像按钮的元素。使用 javascript 函数,它可以识别对详细信息列的点击并采取相应措施。

将此作为附加参数添加到renderReactable 中的reactable 调用。

reactable(
  data = data,
  height = 600,
  defaultPageSize = 20,
  ...
  onClick = JS("function(rowInfo, colInfo) 
    // Only handle click events on the 'details' column
    if (colInfo.id !== 'details') 
      return
    

    // Send the click event to Shiny
    if (window.Shiny) 
      Shiny.setInputValue('foo', 'bar')
    
  ")
)

Shiny.setInputValue("foo", "bar") 将导致服务器的 input$foo 设置为“bar”。这会导致一个 Shiny 事件,您可以在服务器中捕获该事件,例如,使用观察者。见this tutorial about Javascript in R for details。

请注意:reactable 的作者不建议使用此功能,因为“键盘用户目前无法访问自定义点击操作”(引自手册 2021-10-16)。如果可访问性或其他使用键盘的原因与您无关,您可以使用此解决方案。

关于“类”解决方案的注意事项:我不建议使用class = "action-button",因为我认为它是一个脆弱的构造。这不是创建输入绑定的正确方法,我很惊讶它完全可以工作。

我知道的唯一官方支持表格行按钮的包是DataTables 和Buttons extension。

【讨论】:

我从 reactabel 包中知道这些示例,但这些示例都没有进入我在帖子中指出的方向。我需要触发一个模态框,我可以在其中编写 R 代码,而不是 JS 代码。 “显示看起来像按钮的元素”是什么意思?这些是按钮,不是吗? 我不明白。使用Shiny.setInputValue,您可以创建可以通过观察者在 R 服务器函数中处理的事件,并编写您需要编写的任何 R 代码。缺少什么? 关于ui元素看起来像按钮的问题:实际上,它们是假的。单击不响应单击按钮,而是单击整个表格单元格。你可以试试看。即使您单击按钮旁边的几个像素,该演示也会响应您的点击。 您有权使用onClick 参数中的Shiny.setInputValue 处理R 服务器函数中的各种事件,这对我非常有用,谢谢!不过我想知道为什么cell = function(value)div(tags$button(value, onclick = "Shiny.setInputValue('foo', 'bar', priority: 'event')")) 不起作用,因为它基本上看起来完全一样。 不同之处在于两个函数的规范。 reactable 知道 onClick 参数。它是规范的一部分,它提供了运行你放在那里的任何 Javascript 的必要逻辑。另一方面,tags$button 按钮不知道onClick。它接受每个命名参数并将其强制转换为 HTML 属性。但是,当然,这对你没有好处。

以上是关于如何从可反应中的单元格呈现按钮触发带有observeEvent的modalBox?的主要内容,如果未能解决你的问题,请参考以下文章

无法在可反应中呈现没有行数的分组单元格

如何自定义反应表 7 中的列

collectionViewCell 中的按钮不触发功能

如何在 iOS 的 didselectrowatindexpath 中触发按钮操作方法,目标 c

如何使表格视图单元格中的按钮工作[重复]

从可重用单元中出列时,自定义 CollectionViewCell 上会触发啥方法?