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

R Shiny DT表格分页时下拉框选择后跳转首页问题求助

Shiny DT表格分页时选择下拉框自动跳回首页问题解决

问题描述

开发的R Shiny DT表格包含分页功能、内嵌下拉选择框,支持保存更新后的表格为CSV文件。但切换到非首页后,选择下拉框选项时页面会自动跳回首页。

解决方案

核心问题是下拉框触发数据更新时,表格不必要的重绘导致分页状态丢失,同时存在数据修改逻辑冗余。以下是修复后的完整代码及关键改动说明:

关键改动

  • 移除冗余的editData调用,避免重复修改数据触发表格重绘
  • 确保replaceData的resetPaging = FALSE参数正确生效,保留当前分页位置
  • 优化JavaScript中行索引的存储与读取,避免分页时DOM节点索引和实际数据行索引不匹配
  • 删除不必要的事件响应式对象及监听逻辑,减少无效的依赖触发

修复后完整代码

library(shiny)
library(tibble)
library(DT)

# 读取数据(替换为你的文件路径)
data <- read.csv("C:/Users/jyang29/Downloads/saved_data.csv")

ui <- fluidPage(
  DTOutput("myDataTable"),
  actionButton('update', 'Refresh Table'),
  actionButton("saveBtn", "Save as CSV")
)

server <- function(input, output, session) {
  # 响应式存储数据
  rv <- reactiveValues(data = data)
  
  # 渲染DataTable
  output$myDataTable <- renderDataTable({
    datatable(
      rv$data,
      editable = TRUE,
      escape = FALSE,
      selection = 'none',
      options = list(
        columnDefs = list(list(
          targets = 5,
          render = JS(
            "function(data, type, row, meta) {",
            "  if (type === 'display') {",
            "    var dropdownValue = data;",
            "    var rowId = meta.row;",
            "    return '<select class=\"dropdown\" data-row=\"' + rowId + '\">' +",
            "           '<option value=\"setosa\"' + (dropdownValue === 'setosa' ? ' selected' : '') + '>setosa</option>' +",
            "           '<option value=\"versicolor\"' + (dropdownValue === 'versicolor' ? ' selected' : '') + '>versicolor</option>' +",
            "           '<option value=\"virginica\"' + (dropdownValue === 'virginica' ? ' selected' : '') + '>virginica</option>' +",
            "           '</select>';",
            "  }",
            "  return data;",
            "}"
          )
        )),
        preDrawCallback = JS(
          "function() {",
          "  Shiny.unbindAll(this.api().table().node());",
          "}"
        ),
        drawCallback = JS(
          "function() {",
          "  Shiny.bindAll(this.api().table().node());",
          "}"
        ),
        initComplete = JS(
          "function(settings, json) {",
          "  var api = this.api();",
          "  $('.dropdown').on('mousedown', function(e) { e.stopPropagation(); });",
          
          "  $('#myDataTable').on('change', '.dropdown', function() {",
          "    var selectedValue = $(this).val();",
          "    var rowId = $(this).data('row');",
          
          "    Shiny.setInputValue('dropdown_edit', {",
          "      row: rowId + 1,",
          "      col: 5,",
          "      value: selectedValue",
          "    }, {priority: 'event'});",
          "  });",
          "}"
        ),
        buttons = list(
          'copy', 'print', 
          list(
            extend = 'collection',
            buttons = c('csv', 'excel', 'pdf'),
            text = 'Download'
          )
        )
      )
    )
  }, server = TRUE)
  
  # 表格代理
  proxy <- dataTableProxy('myDataTable')
  
  # 监听下拉框修改事件
  observeEvent(input$dropdown_edit, {
    info <- input$dropdown_edit
    i <- info$row
    j <- info$col
    k <- info$value
    
    # 更新响应式数据
    isolate({
      rv$data[i, j] <- DT::coerceValue(k, rv$data[i, j])
    })
    
    # 更新表格,保留分页状态
    replaceData(proxy, rv$data, resetPaging = FALSE)
  })
  
  # 刷新表格按钮
  observeEvent(input$update, {
    replaceData(proxy, rv$data, resetPaging = FALSE)
  })
  
  # 保存为CSV
  observeEvent(input$saveBtn, {
    write.csv(rv$data, "C:/Users/jyang29/Downloads/saved_data.csv", row.names = FALSE)
  })
}

shinyApp(ui, server)

说明

  • 将下拉框修改事件改为独立的dropdown_edit,避免和DT内置的单元格编辑逻辑冲突
  • 使用data-row属性存储DataTable原生的行索引,解决分页时DOM行索引和数据行索引不匹配的问题
  • 简化数据更新流程,仅修改目标单元格并通过replaceData局部更新表格,避免重绘整个表格导致分页重置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:15:55