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

Reactable仅点击行加载详情及DT实现同类交互的技术问询

用DT实现点击行实时加载详情的方案

完全可以用DT实现你需要的工作流——既支持DT原生的整行高亮选中样式,又能做到仅在点击对应行时才触发详情的耗时计算。以下是具体实现方案:


核心实现思路

  • 通过DT的callback配置行点击事件,触发Shiny端的输入更新,传递被点击的行索引
  • 在Shiny服务器端监听该输入,仅当目标行未计算过详情时,才执行复杂算法
  • 配合自定义CSS和JS消息机制,动态渲染详情区域,同时提供加载状态提示

完整代码示例

library(shiny)
library(DT)

ui <- fluidPage(
  tags$head(
    tags$style(HTML("
      /* DT整行高亮选中样式 */
      table.dataTable tr.selected td {
        background-color: #cce5ff !important;
      }
      /* 详情区域样式 */
      .details-row {
        background-color: #f8f9fa;
        padding: 12px;
        border-top: 1px solid #dee2e6;
      }
      .details-loading {
        color: #6c757d;
        font-style: italic;
      }
    "))
  ),
  fluidRow(
    div(DTOutput("atlas_cohort_tbl"), style = "font-size:80%")
  )
)

server <- function(input, output, session) {
  # 模拟2000+行的原始数据
  raw_data <- mtcars[1:2000, 1:5]
  
  # 存储已计算的行详情,避免重复计算
  cached_details <- reactiveVal(list())
  
  # 监听行点击事件,触发详情计算
  observeEvent(input$target_row, {
    row_idx <- input$target_row
    # 仅当未缓存该详情时,执行耗时计算
    if (is.null(cached_details()[[as.character(row_idx)]])) {
      # 替换为你的复杂耗时算法
      Sys.sleep(1) # 模拟计算延迟
      calculation_result <- paste(
        "行", row_idx, "详情:\n",
        "MPG均值偏移:", round(rnorm(1, mean = raw_data[row_idx, "mpg"]), 2), "\n",
        "计算时间:", Sys.time()
      )
      # 更新缓存
      cached_details(c(cached_details(), setNames(list(calculation_result), as.character(row_idx))))
    }
  })
  
  output$atlas_cohort_tbl <- renderDT({
    datatable(
      raw_data,
      selection = "single", # 启用单选模式
      rownames = FALSE,
      callback = JS("
        let expandedRow = null;
        
        // 绑定行点击事件
        table.on('click', 'tr', function() {
          const rowIdx = table.row(this).index() + 1; // 转换为R端的行索引(从1开始)
          Shiny.setInputValue('target_row', rowIdx, {priority: 'event'});
          
          // 切换展开/收起状态
          if (expandedRow === rowIdx - 1) {
            $(this).next('.details-row').remove();
            expandedRow = null;
          } else {
            // 移除已存在的详情行
            $('.details-row').remove();
            // 添加加载状态的占位行
            $(this).after('<tr class=\"details-row\"><td colspan=\"' + table.columns().count() + '\"><div class=\"details-loading\">加载中...</div></td></tr>');
            expandedRow = rowIdx - 1;
          }
        });
        
        // 接收Shiny发送的详情数据,更新前端显示
        Shiny.addCustomMessageHandler('render_details', function(data) {
          const targetRow = table.row(data.row - 1).node();
          const $detailsCell = $(targetRow).next('.details-row').find('td');
          $detailsCell.html('<pre>' + data.content + '</pre>');
        });
      ")
    )
  }, server = FALSE)
  
  # 当缓存更新时,通知前端渲染详情
  observe({
    req(cached_details())
    latest_row <- as.numeric(names(cached_details())[length(cached_details())])
    session$sendCustomMessage(
      "render_details",
      list(row = latest_row, content = cached_details()[[as.character(latest_row)]])
    )
  })
}

shinyApp(ui, server)

关键细节说明

  • 整行高亮:通过自定义CSS覆盖DT的选中样式,完全符合你的使用习惯
  • 懒加载机制:仅在点击行且未缓存详情时才执行计算,避免2000+行提前计算的性能问题
  • 用户体验优化:点击后先显示加载状态,计算完成后再替换为实际结果
  • 展开/收起切换:点击已展开的行会自动收起,同一时间仅显示一行详情

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:33:32