R Shiny - multi-page editable DataTable jumps to row #1 after an edit

烂漫一生 提交于 2019-12-23 12:46:54

问题


I am developing a Shiny app using R 3.3.1, Shiny v. 1.2.0 and v. DT 0.5. One of the elements is an editable data table that spans multiple pages. After I make an edit the row in focus jumps to row #1 which kind of ruins the user experience.

Here are the specific steps to reproduce this using the snippet below:

  1. Load the app
  2. Switch to page 2 of the data table
  3. Edit row 3, column 2: change Duh to Blue and press Tab
  4. Watch the current row jump to page 1 row 1. This would be easier to see if the were many more rows per page.

What I get in step 4 is not the desirable behavior. I want the data table to keep the focus on the same row I just edited.

I am open to using custom JS logic to make this work.

Seemingly related question - DataTable doesn't remember paginated page after edit but I do not know how to bridge from R to JS in this particular example.

 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)

回答1:


In this situation DT::replaceData with resetPaging = FALSE should work fine as shown here. However, defining x as a reactiveValues() cause some problems which I solved using 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)
    })
  }



回答2:


This is my proposal:

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)

I am not sure if it is the cleanest way but it is the best I have been able to do.



来源:https://stackoverflow.com/questions/55215433/r-shiny-multi-page-editable-datatable-jumps-to-row-1-after-an-edit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!