R Shiny如何通过循环批量生成observeEvent列表避免硬编码
Shiny DT动态按钮批量绑定监听事件解决方案
方案1:循环批量生成指定数量的observeEvent
直接替换你代码中硬编码observeEvent的部分即可,核心用lapply+local解决R循环的变量作用域问题,避免所有监听都读取到最后一个循环变量值:
server <- function(input, output) { number_compare <- number_compare %>% mutate( rn = row_number(), button = glue::glue(HTML('<button id="button{rn}" type="button" class="btn btn-default action-button">Ask a question</button>')) ) output$example_table <- DT::renderDT({ datatable( number_compare, escape = FALSE, options=list( preDrawCallback=JS('function() {Shiny.unbindAll(this.api().table().node());}'), drawCallback= JS('function(settings) {Shiny.bindAll(this.api().table().node());}') ) ) }) # 批量生成和数据行数相同的observeEvent,修改seq_len的参数即可指定生成n个 lapply(seq_len(nrow(number_compare)), function(i) { local({ cur_i <- i observeEvent(input[[paste0("button", number_compare$rn[cur_i])]], { # 此处编写对应行的业务逻辑,cur_i为当前点击按钮对应的行号 print(cur_i) }) }) }) }
方案2:更推荐的单监听通用方案(性能更优,不限行数)
不需要生成多个observeEvent,仅用1个全局监听即可处理所有按钮点击,性能远高于批量生成上百个监听的方案:
- 首先修改按钮HTML,增加自定义属性存储行号,删除id属性
number_compare <- number_compare %>% mutate( rn = row_number(), button = glue::glue(HTML('<button type="button" class="btn btn-default action-button dt-custom-btn" data-rn="{rn}">Ask a question</button>')) )
- 在ui的dashboardBody中加入JS监听代码,把点击的行号传给Shiny输入
body <- dashboardBody( tags$script(HTML(" // 监听所有DT表格内按钮的点击事件 $(document).on('click', '.dt-custom-btn', function() { let clickedRn = $(this).data('rn'); // 把行号传给Shiny的input,priority设为event保证每次点击都触发监听 Shiny.setInputValue('clicked_button_rn', clickedRn, {priority: 'event'}); }); ")), fluidRow(box(width = 12, solidHeader = TRUE,DTOutput("example_table"))) )
- server中仅需1个observeEvent处理所有按钮点击
observeEvent(input$clicked_button_rn, { cur_rn <- as.integer(input$clicked_button_rn) # 此处直接用cur_rn处理对应行的业务逻辑即可 print(cur_rn) })
内容的提问来源于stack exchange,提问作者user11740857
相关产品推荐
相关产品推荐

