You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny中DT表格SelectInput二次选择后滚动复位问题求助

解决方案

一、修复selectize控件的滚动跳转问题

问题根源是selectize默认会在激活时将元素滚动到视图中,与DT的横向滚动逻辑冲突。可以通过修改selectize的初始化配置,禁用自动滚动行为并添加滚动位置恢复逻辑:

library(shiny)
library(DT)

# 更新selectize初始化函数,解决滚动跳转问题
selectize_ids <- function(ids) {
  myStrings <- as.character(sapply(ids, function(id) {
    paste0("$('#", id, "').selectize({
      dropdownParent: 'body',
      scrollIntoView: false,
      onDropdownOpen: function() {
        // 记录当前横向滚动位置
        const currentScroll = $('.dataTables_scrollBody').scrollLeft();
        // 延迟恢复滚动位置,避免selectize触发的滚动重置
        setTimeout(() => {
          $('.dataTables_scrollBody').scrollLeft(currentScroll);
        }, 10);
      }
    });")
  }))
  c(
    "function(settings){",
    myStrings,
    "}"
  )
}

shinyApp(
  ui = fluidPage(
    div(style = "display: none;", selectInput(inputId = "dummy", label = NULL, choices = 1:2)),
    fluidRow(DT::dataTableOutput("mytable"))
  ),
  server = function(input, output, session) {
    df <- as.data.frame(matrix(data = paste0("text", 1:60), ncol = 20))
    colnames(df) <- paste0("column", 1:ncol(df))
    df$myselect <- sapply(1:nrow(df), function(i) {
      as.character(selectInput(
        inputId = paste0("myselect_", i),
        label = NULL,
        choices = c("option1", "option2", "option3")
      ))
    })
    select_ids <- paste0("myselect_", 1:nrow(df))
    output$mytable <- DT::renderDataTable({
      DT::datatable(
        data = df,
        escape = F,
        options = list(
          scrollX = TRUE, # 显式开启横向滚动
          initComplete = JS(selectize_ids(select_ids))
        )
      )
    })
  }
)

核心修改说明:

  • scrollIntoView: false:禁用selectize自动将控件滚动到视图的默认行为
  • dropdownParent: 'body':将下拉菜单挂载到body节点,避免被DT的滚动容器裁剪
  • onDropdownOpen钩子:记录当前滚动位置,在下拉菜单打开后强制恢复,阻止页面滚回左侧

二、修复shinyWidgets::pickerInput的liveSearch失效问题

pickerInput在DT表格中liveSearch失效,是因为DT渲染完成后picker组件未被正确初始化,需要手动触发组件刷新:

library(shiny)
library(DT)
library(shinyWidgets)

# 初始化pickerInput的函数
init_pickers <- function(ids) {
  myStrings <- as.character(sapply(ids, function(id) {
    paste0("$('#", id, "').selectpicker('refresh');")
  }))
  c(
    "function(settings){",
    myStrings,
    "}"
  )
}

shinyApp(
  ui = fluidPage(
    fluidRow(DT::dataTableOutput("mytable"))
  ),
  server = function(input, output, session) {
    df <- as.data.frame(matrix(data = paste0("text", 1:60), ncol = 20))
    colnames(df) <- paste0("column", 1:ncol(df))
    df$mypicker <- sapply(1:nrow(df), function(i) {
      as.character(pickerInput(
        inputId = paste0("mypicker_", i),
        label = NULL,
        choices = c("option1", "option2", "option3", "option4", "option5"),
        liveSearch = TRUE,
        options = list(title = "Select option")
      ))
    })
    picker_ids <- paste0("mypicker_", 1:nrow(df))
    output$mytable <- DT::renderDataTable({
      DT::datatable(
        data = df,
        escape = F,
        options = list(
          scrollX = TRUE,
          initComplete = JS(init_pickers(picker_ids))
        )
      )
    })
  }
)

核心修改说明:

  • 在DT的initComplete回调中调用selectpicker('refresh'):强制重新初始化picker组件,确保liveSearch功能正常激活
  • 确保pickerInput的liveSearch参数已设为TRUE

额外优化建议

  • 始终开启DT的scrollX = TRUE:显式启用横向滚动,避免浏览器默认滚动行为干扰控件交互
  • 针对大量行的表格,循环生成控件可能导致性能问题,可考虑使用DT的editable接口结合自定义渲染,或动态加载控件

内容的提问来源于stack exchange,提问作者Ben Ernest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:23:13