R Shiny中renderDT设server=TRUE时无法获取DT表内输入控件值如何解决
问题原因
当renderDT设置server=TRUE时,DT采用服务端渲染模式,仅会将当前可见区域的元素渲染到前端DOM。原代码的回调逻辑仅在表格首次加载时执行一次,后续表格重绘(比如调用reloadData、切换分页)时新生成的输入控件没有完成Shiny绑定,因此服务端无法读取到对应的input值。
解决方法
核心思路是将控件属性设置、Shiny绑定逻辑注册到DT的draw事件中,每次表格重绘完成后都自动对当前渲染的所有输入控件执行解绑+绑定操作,确保所有可见控件都能被Shiny正常识别。
修正后完整可运行代码
library(shiny) library(DT) shinyApp( ui = fluidPage( title = 'Radio buttons in a table', DT::dataTableOutput('foo'), verbatimTextOutput('sel') ), server = function(input, output, session) { m = matrix( as.character(1:5), nrow = 12, ncol = 5, byrow = TRUE, dimnames = list(month.abb, LETTERS[1:5]) ) for (i in seq_len(nrow(m))) { m[i, ] = sprintf( '<input type="radio" name="%s" value="%s"/>', month.abb[i], m[i, ] ) } output$foo = DT::renderDataTable( m, escape = FALSE, selection = 'none', server = TRUE, options = list(dom = 't', paging = FALSE, ordering = FALSE), callback = JS(" // 注册draw事件,每次表格重绘完成后执行绑定 table.on('draw.dt', function() { table.rows().every(function(i, tab, row) { var $this = $(this.node()); $this.attr('id', this.data()[0]); $this.addClass('shiny-input-radiogroup'); }); Shiny.unbindAll(table.table().node()); Shiny.bindAll(table.table().node()); }); // 首次加载手动触发一次绑定 table.draw(); ") ) output$sel = renderPrint({ str(sapply(month.abb, function(i) input[[i]])) }) } )
关键改动说明
- 原回调逻辑仅在表格初始化时执行一次,修改后将逻辑包裹在
table.on('draw.dt', function() {})中,只要表格发生重绘就会自动执行 - 增加了首次加载后的手动draw触发,确保初始渲染的控件能正常完成绑定
- 兼容
reloadData、分页、排序等所有会触发表格重绘的操作场景,修改后所有场景下的输入控件值都可以正常被服务端读取
内容的提问来源于stack exchange,提问作者shobhit_kulshreshtha
相关产品推荐
相关产品推荐

