You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Reactable中点击同一行后modalDialog无法弹出的问题求助

解决Reactable同一行点击无法重复触发Modal的问题

问题原因

你推测的没错:observeEvent(input$foo, ...) 默认只在input$foo的值发生变化时才会执行逻辑。当重复点击同一行时,rowInfo.id没有改变,Shiny.setInputValue传递的是同一个值,所以Shiny不会触发事件。

解决方案1:给输入值添加唯一标识(推荐)

修改onClick的JavaScript函数,每次点击时传递一个包含行ID和时间戳的对象。时间戳每次都不同,能保证input$foo的值每次点击都更新,从而触发observeEvent。

修改后的完整代码:

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

ui <- fluidPage(
  fluidRow(
    column(12, align = 'center', reactableOutput("tbl"))
  )
)

server <- function(input, output, session) {
  
  data = reactive({
    mtcars %>% add_rownames('car')
  })
  
  output$tbl = renderReactable(
    reactable(
      data(),
      defaultPageSize = 10,
      compact = T,
      highlight = T,
      defaultColDef = colDef(headerClass = "bar-sort-header",
                             sortNALast = T, align = 'center',
                             headerVAlign = 'center',
                             vAlign = 'center',
                             minWidth = 60
      ),
      onClick = JS("function(rowInfo, colInfo) {
        // 传递包含行ID和时间戳的对象,确保每次输入值不同
        Shiny.setInputValue('foo', {rowId: rowInfo.id, timestamp: Date.now()}, {priority: 'event'});
      }"),
      rowStyle = list(cursor = "pointer")
    )
  )
  
  observeEvent(input$foo, {
    # 提取行ID
    row_id <- input$foo$rowId
    print(row_id)
    showModal(
      modalDialog(
        size = 'l',
        easyClose = T,
        title = data()$car[as.numeric(row_id)+1],
      )
    )
  })
  
}

shinyApp(ui = ui, server = server)

解决方案2:使用observe替代observeEvent

如果不想修改JS,可以用observe监听input$foo,只要输入被设置就执行逻辑,无需依赖值的变化:

# 仅修改server部分的监听逻辑
server <- function(input, output, session) {
  
  data = reactive({
    mtcars %>% add_rownames('car')
  })
  
  output$tbl = renderReactable(
    reactable(
      data(),
      defaultPageSize = 10,
      compact = T,
      highlight = T,
      defaultColDef = colDef(headerClass = "bar-sort-header",
                             sortNALast = T, align = 'center',
                             headerVAlign = 'center',
                             vAlign = 'center',
                             minWidth = 60
      ),
      onClick = JS("function(rowInfo, colInfo) {
        Shiny.setInputValue('foo', rowInfo.id)
      }"),
      rowStyle = list(cursor = "pointer")
    )
  )
  
  # 用observe替代observeEvent,每次input$foo被设置时都执行
  observe({
    req(input$foo)
    print(input$foo)
    showModal(
      modalDialog(
        size = 'l',
        easyClose = T,
        title = data()$car[as.numeric(input$foo)+1],
      )
    )
  })
  
}

关键说明

  • 方案1通过时间戳确保输入值的唯一性,完全契合Shiny的事件触发机制,是最可靠的解决方式。
  • 方案2利用observe的特性简化逻辑,但需用req(input$foo)避免初始空值触发不必要的执行。

内容的提问来源于stack exchange,提问作者Agrosel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 21:39:36