IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Using the ‘RowReorder’ extension in a Shiny app

    Stéphane Laurent发表于 2024-01-30 00:00:00
    love 0
    [This article was first published on Saturn Elephant, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
    Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

    The ‘RowReorder’ extension of datatables is available in the DT package. This extension allows to reorder the rows of a DT table by dragging and dropping. However, if you enable this extension in a Shiny app for a table using the server-side processing (option server=TRUE in renderDT), that won’t work: each time the rows are reordered, they will jump back to their original locations.

    So, if you want to use the server-side processing, you have to get the new order of the rows whenever they are reordered and then you have to replace the data by applying this new order to it. It is possible to get the new order in JavaScript by listening to the datatables event row-reorder. Then it suffices to send this new order to the Shiny server with the help of Shiny.setInputValue. Here is the JavaScript code which does this job, where n is the number of rows of the data:

    js <- c(
      "table.on('row-reorder', function(e, details, edit) {",
      sprintf("  var order = [%s];", toString(0:(n-1))),
      "  for(entry of details) {",
      "    order[entry.newPosition] = entry.oldPosition;",
      "  }",
      "  Shiny.setInputValue('newOrder', order);",
      "});"
    )

    With this code, whenever the rows are reordered, the Shiny server receives the new order in input$newOrder. So one can use a Shiny observer of this value, in which we can replace the data with the help of the DT function replaceData. One has to keep track of the transformed data for the subsequent reorderings, and we can use a reactive dataframe to do so. Here is the full code of the implementation of this method in a Shiny app:

    library(shiny)
    library(DT)
    
    dat <- data.frame(
      Type  = c("A", "B", "C", "D"),
      Value = c(100, 90, 80, 70)
    )
    
    js <- c(
      "table.on('row-reorder', function(e, details, edit) {",
      sprintf("  var order = [%s];", toString(0:(nrow(dat)-1))),
      "  for(entry of details) {",
      "    order[entry.newPosition] = entry.oldPosition;",
      "  }",
      "  Shiny.setInputValue('newOrder', order);",
      "});"
    )
    
    showRowNames <- TRUE
    
    ui <- fluidPage(
      br(),
      DTOutput("table")
    )
    
    server <- function(input, output, session){
      
      output$table <- renderDT({
        datatable(
          dat,
          rownames = showRowNames,
          extensions = "RowReorder",
          callback = JS(js),
          options = list(rowReorder = TRUE)
        )
      }, server = TRUE)
      
      proxy <- dataTableProxy("table")
      
      Dat <- reactiveVal(dat)
      
      observeEvent(input$newOrder, {
        dat0 <- Dat()
        dat1 <- dat0[input$newOrder + 1, ]
        replaceData(proxy, dat1, resetPaging = FALSE, rownames = showRowNames)
        Dat(dat1)
      })
      
    }
    
    shinyApp(ui, server)
    To leave a comment for the author, please follow the link and comment on their blog: Saturn Elephant.

    R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
    Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
    Continue reading: Using the ‘RowReorder’ extension in a Shiny app


沪ICP备19023445号-2号
友情链接