Search code examples
javascriptrshinydtshinyjs

Shiny DT datatable with scrollY headers mis-aligned when width increased


In my Shiny app, I toggle the width of a DT datatable when a side panel is shown or hidden (using shinyjs addClass() and removeClass()). The table does use scrollY, which I have read can cause issues with misalignment of headers, and indeed, that does happen when the width is expanded.

I noticed that when I click on a header to sort the table, a resizing happens which fixes the issue. In my real app, the resizing also occurs when I click a table row (doesn't happen here, not sure why).

If there isn't a fix for the misalignment issue, how might I manually trigger the resizing that occurs when a header is clicked (perhaps some javascript)?

require(shiny)
require(shinyjs)
require(DT)

shiny::shinyApp(
  ui = fluidPage(
    shinyjs::useShinyjs(),
    shinyjs::inlineCSS(list(.wide = "width: 96%; margin-left: 2%; margin-right: 2%;")),
    shinyjs::inlineCSS(list(.narrow = "width: 70%; margin-left: 2%;")),
    actionButton(inputId = "show_hide_button", label = "Show/hide"),
    fluidRow(
      div(
        id = "side_panel", 
        style = "display: inline-block; width: 25%; vertical-align: top;", 
        h3("Collapsible panel")
      ),
      div(
        id = "main_panel",
        class = "narrow",
        style = "display: inline-block; vertical-align: top;",
        DT::dataTableOutput("my_table")
      )
    )
  ),
  server = function(input, output, session) {
    output$my_table <- DT::renderDataTable({
      DT::datatable(
        data = mtcars,
        options = list(
          scrollY = 480,
          scrollCollapse = T
        )
      )
    })
    
    observeEvent(input$show_hide_button, {
      if(input$show_hide_button %% 2 == 0) {
        shinyjs::removeClass(id = "main_panel", class = "wide")
        shinyjs::addClass(id = "main_panel", class = "narrow")
        shinyjs::show("side_panel")
      } else {
        shinyjs::hide("side_panel")
        shinyjs::removeClass(id = "main_panel", class = "narrow")
        shinyjs::addClass(id = "main_panel", class = "wide")
      }
    })
  }
)

Initial view Initial view After expanding table, headers misaligned After expanding table, headers misaligned Alignment fixed after sorting on 'mpg' column Alignment fixed after sorting on 'mpg' column


Solution

  • You need columns.adjust() here. Call this if the action button is clicked:

    actionButton(
      inputId = "show_hide_button",
      label = "Show/hide",
      onclick = "$($.fn.dataTable.tables(true)).DataTable().columns.adjust().draw();"
    )