如何在Shiny中实现observeEvent响应式 点击按钮输出对应行号
实现方案
问题原因
你原来注释的监听逻辑存在三个核心问题:
- 引用了未定义的
df变量,导致代码无法运行 - 动态生成的
observeEvent没有配置自动销毁,DT每次重绘(如下拉框筛选后)会生成重复的监听事件,导致重复触发、内存泄漏 - 按钮生成时
glue嵌套HTML的写法有问题,会导致按钮id绑定异常
正确实现代码
直接替换即可运行,完整代码如下:
library(shiny) library(shinydashboard) library(DT) library(glue) library(dplyr) library(purrr) number_compare <- data.frame(replicate(2, sample(1:100, 10, rep=TRUE))) sidebar <- dashboardSidebar() body <- dashboardBody( fluidRow(box(width = 12, solidHeader = TRUE, uiOutput("rt"), DTOutput("example_table")) ) ) ui <- dashboardPage(dashboardHeader(title = "Example"), sidebar, body ) server <- function(input, output) { # 生成带按钮的表格数据,修正按钮生成逻辑 number_compare <- number_compare %>% mutate(rn = row_number(), # 生成标准Shiny按钮字符串,避免转义和id绑定问题 button = map_chr(rn, ~as.character(actionButton(paste0("button", .x), "Ask a question")))) output$rt <- renderUI({ selectInput("Sd","Select",choices = number_compare$X1) }) # 响应式存储当前筛选后的所有行的原始行号 current_rn <- reactive({ req(input$Sd) number_compare %>% filter(X1 %in% input$Sd) %>% pull(rn) }) output$example_table <- DT::renderDT({ req(input$Sd) filtered_data <- number_compare %>% filter(X1 %in% input$Sd) datatable( filtered_data, escape = FALSE, options=list( preDrawCallback=JS('function() {Shiny.unbindAll(this.api().table().node());}'), drawCallback= JS('function(settings) {Shiny.bindAll(this.api().table().node());}') ) ) }) # 动态监听当前筛选后所有行的按钮,自动销毁旧监听避免重复触发 observe({ req(current_rn()) lapply(current_rn(), function(x) { id <- paste0("button", x) observeEvent(input[[id]], { # 打印原始数据集行号,如需打印筛选后当前表格内的行号,替换为which(current_rn() == x)即可 cat("点击的行号:", x, "\n") }, ignoreNULL = TRUE, autoDestroy = TRUE) }) }) } shinyApp(ui, server)
改动说明
- 修正按钮生成逻辑,用
purrr::map_chr配合原生actionButton生成按钮,避免id绑定和HTML转义问题 - 新增响应式变量
current_rn存储当前筛选后的行号,避免监听不存在的按钮 - 动态生成监听时配置
autoDestroy = TRUE,DT重绘后旧监听自动销毁,不会出现重复触发问题 - 支持两种行号打印逻辑,可根据需求切换原始行号/当前筛选后行号输出
内容的提问来源于stack exchange,提问作者user11740857
相关产品推荐
相关产品推荐

