2
votes

Having tried out the suggestions in a large number of previous questions on this topic I still can't find anything which works in any sort of acceptable way.

I would like to have a datatable with the first column being a certain width, and the subsequent columns all being the same different width. The number of columns can vary so when the datatable gets too big a horizontal scroll bar appears. This should be something to do with setting columnDefs, autoWidth, and scrollX options (and maybe fillContainer which never seems to get a mention).

Here is my attempt:

library(shiny)
library(DT)
library(data.table)

x <- data.table(rbind(
  expand.grid(tab = 'tab1', cols = c(LETTERS[1:3]), rows = c(letters[1:5])),
  expand.grid(tab = 'tab2', cols = c(LETTERS[1:6]), rows = c(letters[1:5])),
  expand.grid(tab = 'tab3', cols = c(LETTERS[1:26]), rows = c(letters[1:5]))
))
x[, value := rpois(.N,10)]

shinyApp(
  ui = fluidPage(
    selectInput('selected_table', 'Choose table', choices = unique(x$tab), selected = 'tab2'),
    DT::dataTableOutput('table', width = '1000px')
  ),
  server = function(input, output) {
    output$table <- DT::renderDataTable({
      y <- dcast(x[tab == input$selected_table], rows ~ cols, value.var = 'value')
      print(y)
      datatable(y,
        rownames = FALSE,
        options = list(
          autoWidth = TRUE,
          scrollX = TRUE,
          columnDefs = list(
            list(width = '160px', targets = 0),
            list(width = '80px', targets = 1:(ncol(y)-1))
          )
        )
      )
    })
  }
)

When I try this 'tab1' and 'tab2' have the column header row misaligned with the rest of the table (the header is on the left of the page, the body is in the centre). 'tab3' has the scroll bar appearing and only then does it all seem to work. Is there a way to get this to work in all cases?


Stéphane's answer below produces perfect output for the wide table 'tab3', but doesn't produce fixed width columns for 'tab1' and 'tab2'. Is there anything else I can try?

2
Am also surprised we are not getting a proper solution for such a popular R shiny + Javascript interface.Lazarus Thurston

2 Answers

0
votes

Looks like the main cause of the issue is autoWidth. Set it to FALSE. Also use the class dt-center for the columns:

options = list(
  autoWidth = FALSE,
  scrollX = TRUE,
  columnDefs = list(
    list(width = '160px', targets = 0),
    list(width = '80px', targets = 1:(ncol(y)-1)),
    list(className = "dt-center", targets = "_all")
  )
)

And I recommend this CSS when using custom widths:

ui = fluidPage(
  tags$head(tags$style(HTML("table {table-layout: fixed;}"))),
  ......
0
votes

So, adding this line to the ui seems to fix the misaligned header row, while still keeping the fixed column widths.

tags$head(tags$style(".datatables .display {margin-left: 0;}"))

You can still see it creating the table filling all the space, before immediately resizing down to the fixed width, and also the footer line at the bottom still fills all the space too which looks a bit weird.

I'm still interested if anyone has another way to do this.