15
votes

I have a Shiny app that yields a data table, but I can't freeze the first column and the headers, so the table is hard to read as you go down or across. Is there anyway to freeze the panes? I've tried searching but have found nothing.

2
Following recent Shiny update, you might try here and see what sorting options are available datatables.net/upgrade/1.10-convertPork Chop

2 Answers

15
votes

Interesting question and now thanks to the recent update of Shiny to data.tables 1.10.2 it is alot easier to use the various plug-ins and extensions. For your question the FixedHeader extension seems ideal. To add this extension we need to include the relevant JavaScript and CSS file (see http://cdn.datatables.net/):

tagList(
  singleton(tags$head(tags$script(src='//cdn.datatables.net/fixedheader/2.1.2/js/dataTables.fixedHeader.min.js',type='text/javascript'))),
  singleton(tags$head(tags$link(href='//cdn.datatables.net/fixedheader/2.1.2/css/dataTables.fixedHeader.css',rel='stylesheet',type='text/css')))
)

data.tables has an option initComplete which allows us to stipulate a callback once table is drawn etc.

function(settings, json) {
     new $.fn.dataTable.FixedHeader(this, {
                                            left:   true,
                                            right:  true
                                          } );
                                        }

We will use a modified version of the iris data set adding an index and some random data at the end to show left to right scrolling:

library(shiny)
myData <- cbind(list(index = row.names(iris)), iris
                , rep(list(row.names(iris)), 10))
names(myData)[7:16] <- paste0("randomData", 1:10)
runApp(
  list(ui = fluidPage(
    tagList(
      singleton(tags$head(tags$script(src='//cdn.datatables.net/fixedheader/2.1.2/js/dataTables.fixedHeader.min.js',type='text/javascript'))),
      singleton(tags$head(tags$link(href='//cdn.datatables.net/fixedheader/2.1.2/css/dataTables.fixedHeader.css',rel='stylesheet',type='text/css')))
    ), 

    dataTableOutput("mytable")
  )
  , server = function(input, output, session){
    output$mytable <- renderDataTable(myData,
                                      options = list(
                                        pageLength = 50,
                                        initComplete = I("function(settings, json){
                                          new $.fn.dataTable.FixedHeader(this, {
                                            left:   true,
                                            right:  true
                                          } );
                                        }")
                                      )
    )
  })
)

so in the image we can see we are scrolled down to record 8 and across some ways but the header and the first column (our added index column) are still visible.

enter image description here

9
votes

FixedHeader is now (2021) compatible with FixedColumns. See table

library(shiny)
library(DT)
runApp(
  list(ui = fluidPage(
    
    dataTableOutput("mytable")
  )
  , server = function(input, output, session){
    Rows <- c(1:30)
    for (y in 1:15){
      x<-y-1
      assign(letters[x+1],runif(5, 0, 1))
    }
    x <- data.frame(Rows, mget(letters[1:15]), row.names=NULL) 
    x<- x[2:15]
    output$mytable <- renderDataTable(
      DT::datatable(x, rownames=FALSE,extensions = c('FixedColumns',"FixedHeader"), 
                    options = list(dom = 't', 
                                   scrollX = TRUE, 
                                   paging=FALSE,
                                   fixedHeader=TRUE,
                                   fixedColumns = list(leftColumns = 1, rightColumns = 0))
      )
    )
  } 
  )
)

Implemented:

2021-09-10: FixedColumns 4.0.0