Using scrollTo() in shiny DT skips rows

This is cross-posted to stack overflow but I find I often get more response over here. I have a shiny app that uses DT to display some data. At some point, I have a list of rows (row numbers) I want to navigate directly to using a button attached to the datatable object. I've come up with a method of doing it, but for some reason, it only navigates to some rows and not to others. Strangely, the rows it refuses to navigate to seem consistent over and over. If I re-run the app, it will fail to navigate to the same ones each time. In the attached example, the rows I want to jump to are 8, 10, 29, 30, 68, 78, 99, 103, 104, 108, 109, 112, 120, 122, 128. For some reason, once it gets to 109, the scrollTo call does nothing until the number cycles back to 8. I initially tried this with the numbers in random order and thinking they needed to be sorted, I tried that, with the same result. Interestingly, the rows that don't work are the highest 5 (109, 112, 120, 122, and 128). I can't see any reason why it would be behaving this way. Anybody have any insight?

Also, if there's a better way of doing this, I'd love to know. It does seem a little kludgy to send the row numbers by message and then loop through them elsewhere in javascript.

Run the example below and hit the next button a bunch of times. You'll (hopefully) see that it reaches a point where the datatable no longer jumps to the next row until the index cycles back to the beginning. These numbers are all within the max rows of the dataframe (iris).

library(shiny)
library(DT)

ui <- shinyUI({
  fluidPage(
    tags$head(
      tags$script("
        var row_index = 0;
        var view_rows = [];
        Shiny.addCustomMessageHandler('set-rows',function(rows) {
          view_rows = rows;
          row_index = 0;
        })
      ") 
    ),
    textOutput("row_list"),
    DTOutput("tabs")
  )
})

server <- shinyServer(function(input,output,session) {
  
  view_rows <- reactive({
    c(111, 9, 108, 77, 67, 7, 103, 28, 98, 29, 121, 119, 127, 102, 107)
    # sample(1:nrow(iris),15)
  })
  
  output$row_list <- renderText({
    paste(view_rows()+1,collapse=", ")
  })
  
  observe({
    print("sending rows")
    session$sendCustomMessage("set-rows",view_rows())
  })
  
  
  output$tabs <- renderDT({
    datatable(
      iris,
      extensions = c("Buttons","Scroller"),
      options = list(
        dom = 'BfrtSip',
        scroller = TRUE,
        selection = "single",
        scrollY = "60vh",
        buttons = list(
          list(
            extend = "collection",
            text = "next",
            action = DT::JS("
              function ( e, dt, node, config ) {
                console.log('going to ' + view_rows[row_index]);
                dt.row(view_rows[row_index++]).scrollTo(false);
                if (row_index >= view_rows.length) {
                  row_index = 0;
                }
              }
            ")
          )
        )
      )
    )
  })
})

shinyApp(ui,server)

Ok I've done a bit more playing around it just gets weirder. It looks like, no matter what dataset I use, there is some upper limit for which row index will work with scrollTo. If I just call it with integers, that upper limit appears to by 188 (actually 189 since rows are zero-indexed in datatables). Here's a more stripped down version of the example I gave in my previous post. This version works as expected (i.e. you hit the button and it jumps to a row):

library(shiny)
library(DT)


shinyApp(
  ui = shinyUI({
    fluidPage(
      DTOutput("table")
    )
  }),
  server = shinyServer(function(input,output,session) {
    output$table <- renderDT({
      datatable(
        ChickWeight,
        extensions = c("Buttons","Scroller"),
        # callback = DT::JS("window.dt = table;"),
        options = list(
          dom = 'BfrtSip',
          scroller = TRUE,
          paging = TRUE,
          selection = "single",
          scrollY = "60vh",
          buttons = list(
            list(
              extend = "collection",
              text = "next",
              action = DT::JS("
              function ( e, dt, node, config ) {
                dt.row(188).scrollTo(false);
              }
            ")
            )
          )
        )
      )
    })
  })
)

But if you change 188 to 189, it doesn't work. WHAT'S HAPPENING HERE?!
Notably, if I run this in a browser (rather than the RStudio popup), the maximum number is 89 in Firefox and 98 in Safari (the two browsers I was able to test it in). This is really driving me crazy! No javascript errors show up in the browser console so something must just be dying silently. WHAT GIVES?!

In order to rule out whether it was something weird happening locally, I tried running this on a remote linux server and connecting with my (local) browser. I got the same behavior but different numbers. Running this on Ubuntu 20.04 using the above example code, the max number for firefox was 53. I didn't have the patience to track down the max number for safari but it was somewhere between 95 and 120.

What in the world is going on?!

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.