如何在reactable表格中通过双击事件触发模态窗口
Reactable单元格双击触发模态窗口并获取行索引解决方案
问题需求
我希望在reactable表格的单元格上触发双击事件以打开模态窗口,同时需要获取行索引,以便在模态窗口中显示对应行的图片。
现有代码可实现双击最后一列时弹出window.alert,但我更擅长用R编写代码,想要实现功能更丰富的模态窗口:
library(shiny) library(tidyverse) library(reactable) ui <- fluidPage( fluidRow( column(12, align = 'center',reactableOutput("tbl")) ) ) server <- function(input, output, session) { data = reactive({mtcars %>% tibble::rownames_to_column('car')}) output$tbl = renderReactable( reactable( data(), columns = list( carb = colDef( sticky = "right", sortable = FALSE, cell = function(value, index, name){ icon("globe", ondblclick = sprintf("window.alert('double clicked cell %s in column %s')", index, name) ) }) ), compact = T, highlight = T, onClick = JS(" function(rowInfo, colInfo, column) { if (colInfo.id !== 'carb') { Shiny.setInputValue('qwert', {id:rowInfo.id, nonce:Math.random()}); } }"), rowStyle = list(cursor = "pointer") ) ) observeEvent(input$qwert, { print(input$qwert) id <- input$qwert$id row_nr <- as.numeric(id)+1 showModal( modalDialog( size = 'l', easyClose = T, title = data()$car[row_nr], "some text" ) ) }) observeEvent(input$poiu, { print(input$poiu) id2 <- input$poiu$id row_nr2 <- as.numeric(id2)+1 showModal( modalDialog( title = data()$car[row_nr2], "double click" ) ) }) } shinyApp(ui = ui, server = server)
我尝试了以下几种写法,均未成功:
sprintf(Shiny.setInputValue('poiu', {nonce:Math.random()})):仅尝试触发模态窗口ondblclick = sprintf(Shiny.setInputValue('poiu', {id:%s.id, nonce:Math.random()}), index)cell = function(value, index){ icon("globe", ondblclick = shinyjs::runjs(paste0("shiny.setInputValue('poiu',", index)) )}
解决方案
修正后的完整代码
library(shiny) library(tidyverse) library(reactable) ui <- fluidPage( fluidRow( column(12, align = 'center', reactableOutput("tbl")) ) ) server <- function(input, output, session) { data = reactive({mtcars %>% tibble::rownames_to_column('car')}) output$tbl = renderReactable( reactable( data(), columns = list( carb = colDef( sticky = "right", sortable = FALSE, cell = function(value, index, name){ # 关键修正:正确生成双击触发的JS代码,传递行索引到Shiny输入 icon("globe", ondblclick = sprintf( "Shiny.setInputValue('poiu', {id: '%s', nonce: Math.random()})", index ) ) }) ), compact = T, highlight = T, onClick = JS(" function(rowInfo, colInfo, column) { if (colInfo.id !== 'carb') { Shiny.setInputValue('qwert', {id:rowInfo.id, nonce:Math.random()}); } }"), rowStyle = list(cursor = "pointer") ) ) observeEvent(input$qwert, { print(input$qwert) id <- input$qwert$id row_nr <- as.numeric(id)+1 showModal( modalDialog( size = 'l', easyClose = T, title = data()$car[row_nr], "some text" ) ) }) observeEvent(input$poiu, { print(input$poiu) id2 <- input$poiu$id # 注意:reactable的index从1开始,无需+1 row_nr2 <- as.numeric(id2) showModal( modalDialog( size = 'l', easyClose = T, title = data()$car[row_nr2], # 这里可以替换为对应行的图片,比如:img(src = data()$image_url[row_nr2]) paste0("这是第", row_nr2, "行的内容") ) ) }) } shinyApp(ui = ui, server = server)
关键修改说明
- 双击事件的JS代码生成:
在cell函数中,通过sprintf正确拼接JavaScript代码,将index(行索引,从1开始)作为字符串传递给Shiny.setInputValue,同时添加nonce: Math.random()确保Shiny能检测到输入值的变化(避免重复点击不触发事件)。 - 行索引的处理:
reactable的index参数本身就是从1开始的行号,因此在observeEvent(input$poiu)中无需再加1,直接转换为数值即可获取对应行。 - 模态窗口内容扩展:
可以在模态窗口中直接添加图片元素,比如img(src = data()$image_column[row_nr2]),只需将data()中的对应图片列替换为实际的图片URL列即可。
内容的提问来源于stack exchange,提问作者Julie R
相关产品推荐
相关产品推荐

