Collapse rowGroup Shiny

狂风中的少年 提交于 2020-12-30 03:43:54

问题


I have rather simple application (below) where I try to output grouped table using DataTable with the ability to collapse the groups. I found solution in that is implemented in jQuery here but I have no idea how such complex implementation could be moved into R.

Currently, I am able to collapse within a group but not the whole group itself. Any hints how this could be implemented in Shiny?

My application:

library(shiny)
library(DT)
library(shinyjs)

ui <- fluidPage(

   # Application title
   titlePanel("Collapse/Expand table"),

            mainPanel(
          DTOutput("my_table")

      )
   )


server <- function(input, output) {

    output$my_table<-DT::renderDataTable({

        datatable(mtcars[1:15,1:5],
                  extensions = 'RowGroup', 
                  options = list(rowGroup = list(dataSrc=c(3)),
                                 pageLength = 20),
                  callback = JS("
                                table.on('click', 'tr', function () {
                                    var rowsCollapse = $(this).nextUntil('.group');
                                    $(rowsCollapse).toggleClass('hidden');
                                 });"))
    })
}

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

EDIT

Given AEF comment one can adjust the code to specify that even has to take place once table body is clicked. This indeed collapses any rows until next group. The remaining part is to restrict the clicks only onto group rows. The callback should be now:

callback = JS("$('#DataTables_Table_0 tbody').on('click', 'tr', function () {
 $(this).nextUntil('.group').toggleClass('hidden');});"))

回答1:


It turns out to be a bug of DT's javascript code. There's a click event listener that will record all the info of the clicked cells. However, the RowGroup extension creates a new row that doesn't belong to the original datasets and leads to an error. This error stops the further javascript executions.

In your cases, the tr.group event doesn't work because of the error thrown from the previous cell-click event.

We've fixed this bug and the dev version of DT should work with the below code:

library(shiny)
library(DT)
ui <- fluidPage(# Application title
  titlePanel("Collapse/Expand table"),
  mainPanel(DTOutput("my_table")))

callback_js <- JS(
  "table.on('click', 'tr.dtrg-group', function () {",
  "  var rowsCollapse = $(this).nextUntil('.dtrg-group');",
  "  $(rowsCollapse).toggleClass('hidden');",
  "});"
)

server <- function(input, output) {
  output$my_table <- DT::renderDT({
    datatable(
      mtcars[1:15, 1:5],
      extensions = 'RowGroup',
      options = list(rowGroup = list(dataSrc = 3), pageLength = 20),
      callback = callback_js,
      selection = 'none'
    )
  })
}

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

Thanks again for you reports!

Ticker to the Github issue of DT: https://github.com/rstudio/DT/issues/759




回答2:


Just one other note on this. I noticed that in a standard fluidPage etc, this worked as expected. However, it stopped working when I started using it in an htmlTemplate.

Somewhere along the way, it loses the .hidden class and I had to manually add it.

.hidden {
  display: none !important;
}

Then it worked as expected.




回答3:


Thanks to the AEF comment I was able to boil down the problem. The event has to occur one user clicks on the body $('#DataTables_Table_0 tbody') and only on rows with group identifier 'tr.group'.

The final callback has to be adjusted to take both of those conditions into account.

Therefore application with collapsable rows looks as follows:

library(shiny)
library(DT)
library(shinyjs)

ui <- fluidPage(

   # Application title
   titlePanel("Collapse/Expand table"),

            mainPanel(
          DTOutput("my_table")

      )
   )


server <- function(input, output) {

    output$my_table<-DT::renderDataTable({

        datatable(mtcars[1:15,1:5],
                  extensions = 'RowGroup', 
                  options = list(rowGroup = list(dataSrc=c(3)),
                                 pageLength = 20),
                  callback = JS("
                                $('#DataTables_Table_0 tbody').on('click', 'tr.group', function () {
                                    var rowsCollapse = $(this).nextUntil('.group');
                                    $(rowsCollapse).toggleClass('hidden');
                                 });"))
    })
}

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



回答4:


As mentioned by @David Joequera in the comments this is a JavaScript error, where one of the default event Handlers of Datatable throws an Error because the row porperty doesn't exist in the Group row.

As a work around we can remove this event handler so that the one for hiding will work.

Also i would recommend you to only target the group rows with the event handler so that you can only fully close and open the groups and can not semi hide groups. You can achieve this by simply adding a ".group" to your event Listener Target. Resulting in this code:

table.on('click', 'tr.group', function () {
   var rowsCollapse = $(this).nextUntil('.group');
   $(rowsCollapse).toggleClass('hidden');
})

In order to remove the event Handler we will need to wait until the table is properly loaded and the problematic event handler is atached so I would recommend working with a small timeout. 1000 ms worked fine for me and should not bring any usability issues. so adding this code to the Callbacks should fix the issue:

setTimeout(function(){$('#DataTables_Table_0').off('click.dt','tbody td')},1000);

Be aware that the the ID of the DataTable to delete might change in your final/real solution

Resulting in this code for the demo:

library(shiny)
library(DT)
library(shinyjs)

ui <- fluidPage(

  # Application title
  titlePanel("Collapse/Expand table"),

  mainPanel(
    DTOutput("my_table")

  ),
)


server <- function(input, output) {

output$my_table<-DT::renderDataTable({

datatable(mtcars[1:15,1:5],
          extensions = 'RowGroup', 
          options = list(rowGroup = list(dataSrc=c(3)),
                         pageLength = 20),
          callback = JS("
                           setTimeout(function(){$('#DataTables_Table_0').off('click.dt','tbody td')},1000);
                           table.on('click', 'tr.group', function () {
                                var rowsCollapse = $(this).nextUntil('.group');
                                $(rowsCollapse).toggleClass('hidden');
                             });"))
})



}

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


来源:https://stackoverflow.com/questions/59896704/collapse-rowgroup-shiny

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