无法用ShinyJS禁用Shiny DT中的复选框,求解决方案
解决Shiny DT表格中ShinyJS无法禁用复选框的问题
问题根源
你调用shinyjs::disable("chkbx_1")的时机错误——在DT表格完成渲染前,页面DOM中还不存在chkbx_1这个复选框元素,导致禁用指令无法作用到目标控件上。
解决方案
提供两种可行方案,根据你的需求选择:
方案一:生成复选框时直接添加禁用属性(适合固定禁用场景)
如果一开始就确定要禁用特定行的复选框,可以在生成复选框时直接传入disabled = TRUE参数:
library("DT") library("shinyjs") ui <- basicPage( h2("The mtcars data"), useShinyjs(), DT::dataTableOutput("mytable") ) server <- function(input, output) { shinyInput <- function(FUN, len, id, ...) { inputs <- as.character(FUN(paste0(id,'_', len), ...)) inputs } mtcarsx <- data.frame(mtcars) for(myrow in 1:nrow(mtcarsx)){ # 行号为1时添加禁用属性 if(myrow == 1){ mtcarsx[myrow,"newvar"] = toString(shinyInput(checkboxInput, toString(myrow), "chkbx", label="", value=FALSE, width=NULL, disabled = TRUE)) } else { mtcarsx[myrow,"newvar"] = toString(shinyInput(checkboxInput, toString(myrow), "chkbx", label="", value=FALSE, width=NULL)) } } output$mytable = DT::renderDataTable({ DT::datatable(mtcarsx, escape = FALSE, selection = 'none', rownames = TRUE, extensions = c('FixedColumns'), options = list(searching = FALSE, ordering = FALSE, autoWidth = TRUE, scrollX = TRUE, FixedColumns = list(leftColumns = c(2)) )) }) } shinyApp(ui, server)
方案二:表格渲染完成后执行禁用操作(适合动态控制场景)
如果需要动态控制复选框的禁用状态,可利用DT的initComplete回调函数,在表格完全渲染到页面后执行禁用逻辑:
library("DT") library("shinyjs") ui <- basicPage( h2("The mtcars data"), useShinyjs(), DT::dataTableOutput("mytable") ) server <- function(input, output) { shinyInput <- function(FUN, len, id, ...) { inputs <- as.character(FUN(paste0(id,'_', len), ...)) inputs } mtcarsx <- data.frame(mtcars) for(myrow in 1:nrow(mtcarsx)){ mtcarsx[myrow,"newvar"] = toString(shinyInput(checkboxInput, toString(myrow), "chkbx", label="", value=FALSE, width=NULL)) } output$mytable = DT::renderDataTable({ DT::datatable(mtcarsx, escape = FALSE, selection = 'none', rownames = TRUE, extensions = c('FixedColumns'), options = list( searching = FALSE, ordering = FALSE, autoWidth = TRUE, scrollX = TRUE, FixedColumns = list(leftColumns = c(2)), # 表格初始化完成后执行禁用 initComplete = JS( "function(settings, json) {", " $('#chkbx_1').prop('disabled', true);", "}" ) )) }) } shinyApp(ui, server)
也可以使用Shiny事件监听替代initComplete(需将server参数改为function(input, output, session)):
# 在server函数中添加以下代码 observeEvent(input$mytable_rows_all, { shinyjs::disable("chkbx_1") }, once = TRUE) # 确保只执行一次
原理说明
- 方案一直接在生成复选框的HTML代码中嵌入
disabled属性,控件加载时就处于禁用状态,无需依赖后续JS操作。 - 方案二通过
initComplete或Shiny事件监听,确保在DOM元素(复选框)已存在的情况下执行禁用指令,解决了原代码中时机过早的问题。
内容的提问来源于stack exchange,提问作者stat
相关产品推荐
相关产品推荐

