How can I fix the position of the header of data.table in shiny-app

765 views Asked by At

Let say I have below app -

library(shiny)
library(DT)
library(dplyr)

ui <- fluidPage(
  div(style = "height: 300px; width: 100%; overflow-y: scroll;", DTOutput("aaa", height = '400px'))
)

server <- function(input, output) {
  output$aaa = 
            DT::renderDT({
            df = 
            structure(list(Col__1 = c("A", "A", "A", "A", "B", "C", "C", 
"D", "G", "G", "H", "H", "J", "K", "K", "M", "M", "M", "M", "M", 
"O", "P", "P", "R", "T", "T", "T", "U", "U", "W"), Col__2 = c(1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234), Col__3 = c(1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234), Col__4 = c(NA, 36, NA, 1, 
4, 1, NA, 65, NA, 396, 7, 2, 3, 29, 4, 185, 651, NA, 1, NA, 2, 
NA, 27, 92, 35, 29, NA, 60, 1, 144), Col__5 = c(NA, 1012, NA, 
12, 350, 98, NA, 3925, NA, 4729, 327, 5, 87, 310, 30, 1854, 13013, 
NA, 1, NA, 122, NA, 1354, 1629, 3278, 450, NA, 1808, 21, 948), 
    Col__6 = c(1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
    1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
    1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
    1234, 1234), Col__7 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
    Col__8 = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), Col__9 = c("-", 
    " 36 (2%)", "-", "  1 (2%)", "  4 (1%)", "  1 (1%)", "-", 
    " 65 (1%)", "-", "396 (6%)", "  7 (1%)", "  2 (4%)", "  3 (2%)", 
    " 29 (4%)", "  4 (1%)", "185 (6%)", "651 (4%)", "-", "  1 (8%)", 
    "-", "  2 (1%)", "-", " 27 (2%)", " 92 (3%)", " 35 (1%)", 
    " 29 (3%)", "-", " 60 (2%)", "  1 (2%)", "144 (10%)"), Col__10 = c(2.5, 
    2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 
    2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 
    2.5, 2.5, 2.5, 2.5, 2.5)), row.names = c(NA, -30L), class = "data.frame")

{  ### Few Important Definitions
                    Render3 = JS(
                                "function(data, type, row, meta){",
                                "  if(type === 'sort' || type === 'type'){",
                                "    return row[4];",
                                "  } else {",
                                "    return data;",
                                "  }",
                                "}"
                            )
                }

datatable(df, 
          callback = JS("$('table.dataTable.no-footer').css('border-bottom', '1px solid #b7b7b7');"),
          options = list(pageLength = dim(df)[1], bLengthChange = FALSE, autoWidth = FALSE, bInfo = FALSE, searching = FALSE, info = FALSE, bPaginate = FALSE,
                          order = list(list(7, 'desc')),
                          columnDefs = 
                              list(
                                  list(width = '40%', targets = 1, className = 'dt-center dt-center1'), 

                                  list(width = '0%', targets = 2, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 3, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 4, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 5, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 6, className = 'dt-center dt-center1', visible = FALSE),


                                  list(width = '15%', targets = 9,  className = 'dt-center dt-center1', visible = TRUE, render = Render3),


                                  list(targets = 0, visible = FALSE)
                              ))) 
        })
}
shinyApp(ui, server)

As you see, if I scroll down of the container div, then I am losing the view of the header of the data.table. Is there any way to fix the position of the header in the current position?

Any pointer will be highly helpful.

Update after answer from Stéphane Laurent

Updated app with FixedHeader

library(shiny)
library(DT)
library(dplyr)

ui <- fluidPage(
  tags$link(rel = "stylesheet", type = "text/css", href = "https://cdn.datatables.net/v/dt/dt-1.10.21/datatables.min.css"),
  tags$script(src='https://cdn.datatables.net/v/dt/dt-1.10.21/fh-3.1.7/datatables.min.js'),
  div(style = "height: 300px; width: 100%; overflow-y: scroll;", DTOutput("aaa", height = '400px'))
)

server <- function(input, output) {
  output$aaa = 
            DT::renderDT({
            df = 
            structure(list(Col__1 = c("A", "A", "A", "A", "B", "C", "C", 
"D", "G", "G", "H", "H", "J", "K", "K", "M", "M", "M", "M", "M", 
"O", "P", "P", "R", "T", "T", "T", "U", "U", "W"), Col__2 = c(1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234), Col__3 = c(1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
1234, 1234, 1234, 1234, 1234, 1234), Col__4 = c(NA, 36, NA, 1, 
4, 1, NA, 65, NA, 396, 7, 2, 3, 29, 4, 185, 651, NA, 1, NA, 2, 
NA, 27, 92, 35, 29, NA, 60, 1, 144), Col__5 = c(NA, 1012, NA, 
12, 350, 98, NA, 3925, NA, 4729, 327, 5, 87, 310, 30, 1854, 13013, 
NA, 1, NA, 122, NA, 1354, 1629, 3278, 450, NA, 1808, 21, 948), 
    Col__6 = c(1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
    1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
    1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 
    1234, 1234), Col__7 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
    Col__8 = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), Col__9 = c("-", 
    " 36 (2%)", "-", "  1 (2%)", "  4 (1%)", "  1 (1%)", "-", 
    " 65 (1%)", "-", "396 (6%)", "  7 (1%)", "  2 (4%)", "  3 (2%)", 
    " 29 (4%)", "  4 (1%)", "185 (6%)", "651 (4%)", "-", "  1 (8%)", 
    "-", "  2 (1%)", "-", " 27 (2%)", " 92 (3%)", " 35 (1%)", 
    " 29 (3%)", "-", " 60 (2%)", "  1 (2%)", "144 (10%)"), Col__10 = c(2.5, 
    2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 
    2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 
    2.5, 2.5, 2.5, 2.5, 2.5)), row.names = c(NA, -30L), class = "data.frame")

{  ### Few Important Definitions
                    Render3 = JS(
                                "function(data, type, row, meta){",
                                "  if(type === 'sort' || type === 'type'){",
                                "    return row[4];",
                                "  } else {",
                                "    return data;",
                                "  }",
                                "}"
                            )
                }

datatable(df, extensions = "FixedHeader", 
          callback = JS("$('table.dataTable.no-footer').css('border-bottom', '1px solid #b7b7b7');"),
          options = list(fixedHeader = TRUE,pageLength = dim(df)[1], bLengthChange = FALSE, autoWidth = FALSE, bInfo = FALSE, searching = FALSE, info = FALSE, bPaginate = FALSE,
                          order = list(list(7, 'desc')),
                          columnDefs = 
                              list(
                                  list(width = '40%', targets = 1, className = 'dt-center dt-center1'), 

                                  list(width = '0%', targets = 2, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 3, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 4, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 5, className = 'dt-center dt-center1', visible = FALSE),
                                  list(width = '0%', targets = 6, className = 'dt-center dt-center1', visible = FALSE),


                                  list(width = '15%', targets = 9,  className = 'dt-center dt-center1', visible = TRUE, render = Render3),


                                  list(targets = 0, visible = FALSE)
                              ))) 
        })
}
shinyApp(ui, server)

I still dont see the header remained at fixed position under the current setup. However if I remove the styling overflow-y: scroll then it is working. Is there any workaround?

1

There are 1 answers

1
Stéphane Laurent On

Does the FixedHeader extension suits your need?

library(DT)

datatable(iris, extensions = "FixedHeader", 
          options = list(
            fixedHeader = TRUE
          )
)