【问题标题】:R Shiny - multi-page editable DataTable jumps to row #1 after an editR Shiny - 多页可编辑数据表在编辑后跳转到第 1 行
【发布时间】:2019-08-08 11:18:36
【问题描述】:

我正在使用 R 3.3.1、Shiny v. 1.2.0 和 v. DT 0.5 开发一个 Shiny 应用程序。其中一个元素是跨多个页面的可编辑数据表。在我进行编辑后,焦点所在的行会跳转到第 1 行,这会破坏用户体验。

以下是使用下面的 sn-p 重现此问题的具体步骤:

  1. 加载应用程序
  2. 切换到数据表的第 2 页
  3. 编辑第 3 行第 2 列:将 Duh 更改为蓝色并按 Tab 键
  4. 观看当前行跳转到第 1 页第 1 行。这样可以更容易地查看每页是否有更多行。

我在第 4 步得到的并不是理想的行为。我希望数据表将焦点保持在我刚刚编辑的同一行上。

我愿意使用自定义 JS 逻辑来完成这项工作。

看似相关的问题 - DataTable doesn't remember paginated page after edit 但在这个特定示例中我不知道如何从 R 桥接到 JS。

 R.version.string
# "R version 3.3.1 (2016-06-21)"

library(shiny)  # v. 1.2.0
library(DT)  # v. 0.5

page_length <- 2 # 5 elements should span 3 pages

hardcoded_df <- read.table(text = "Fruit Color
                                   Apple Red
                                   Plum Purple
                                   Blueberry Duh
                                   Orange Carrot
                                   Crocodile Green",
                           header = TRUE,
                           stringsAsFactors = FALSE)

ui <- fluidPage(
   DT::dataTableOutput('x1')
)

server <- function(input, output) {
  x = reactiveValues(df = hardcoded_df)

   output$x1 = renderDT(DT::datatable(x$df, options = list(pageLength = page_length), selection = 'none', editable = TRUE))

   proxy = dataTableProxy('x1')

   observeEvent(input$x1_cell_edit, {
     info = input$x1_cell_edit
     str(info)

     # str(input$x1_state)
     i = info$row
     j = info$col
     v = info$value

     # Without this line the table does not change but with it it jumps to row 1 after an edit.
     x$df[i, j] <- isolate(DT::coerceValue(v, x$df[i, j]))

     # Now we need to scroll to row i somehow ... clearly this does not work. Help!
     selectPage(proxy, ceiling(i / page_length))
     # selectRow(proxy, i)
   })
}

# Run the application 
shinyApp(ui = ui, server = server)

【问题讨论】:

    标签: r shiny dt


    【解决方案1】:

    在这种情况下DT::replaceDataresetPaging = FALSE 应该可以正常工作,如here 所示。但是,将x 定义为reactiveValues() 会导致一些问题,我使用isolate 解决了这些问题

     server <- function(input, output, session) {
        x = reactiveValues(df = hardcoded_df)
        output$x1 = renderDT(DT::datatable(isolate(x$df), 
                    options = list(pageLength = page_length), selection = 'none', editable = TRUE))
    
        proxy = dataTableProxy('x1')
    
        data = reactiveValues()
        observeEvent(input$x1_cell_edit, {
          info = input$x1_cell_edit
          str(info)
          # str(input$x1_state)
          i = info$row
          j = info$col
          v = info$value
    
          # Without this line the table does not change but with it it jumps to row 1 after an edit.
          x$df[i, j] <- isolate(DT::coerceValue(v, x$df[i, j]))
          DT::replaceData(proxy, x$df, resetPaging = FALSE)  # important
          # Now we need to scroll to row i somehow ... clearly this does not work. Help!
          #selectPage(proxy, ceiling(i / page_length))
          # selectRow(proxy, i)
        })
      }
    

    【讨论】:

    • 谢谢。除了添加DT::replaceData(proxy, x$df, resetPaging = FALSE) # important 之外,您是否进行了其他更改?我无法在视觉上发现任何其他人。我问是因为我的生产代码与这个玩具示例有很大不同,所以我不能只是复制和粘贴整个服务器功能。
    • @Leonid 不客气。我做了三处修改,1-评论selectPage(proxy, ceiling(i / page_length))。 2- 添加DT::replaceData(proxy, x$df, resetPaging = FALSE)。 3- 在renderDT 中添加isolate(x$df)
    • 酷,我确认这完全解决了我的问题 - 页面和行现在都保持焦点,所以我将此答案标记为已接受。
    【解决方案2】:

    这是我的建议:

    server <- function(input, output) {
      x = reactiveValues(df = hardcoded_df)
    
      output$x1 = renderDT(DT::datatable(x$df, options = list(pageLength = page_length), selection = 'none', editable = TRUE))
    
      observeEvent(input$x1_cell_edit, {
        info = input$x1_cell_edit
        str(info)
    
        # str(input$x1_state)
        i = info$row
        j = info$col
        v = info$value
    
        # Without this line the table does not change but with it it jumps to row 1 after an edit.
        proxy = dataTableProxy('x1')
        newdf <-  x$df
        newdf[i,j] <- coerceValue(v, newdf[i, j])
        print(newdf)
        replaceData(proxy, newdf,resetPaging = F)
    
        # selectRow(proxy, i)
      })
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)
    

    我不确定这是否是最干净的方式,但这是我能做到的最好的方式。

    【讨论】:

    • 谢谢。显然这条线需要改变,否则它将不起作用。请参阅上面的答案。 output$x1 = renderDT(DT::datatable(x$df ...
    猜你喜欢
    • 1970-01-01
    • 2016-07-12
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    相关资源
    最近更新 更多