Max M Max M - 3 months ago 48
R Question

Dynamic column alignment in DT datatable

I have a larger datatable output with varying number of columns, which I chose in my widget. I would like to dynamically right align my columns,but only found a solution if the number of columns is fixed. I was hoping I could just adjust the reference in the target= command to make it dynamic. Somehow this does not work and I do not get an output when the number of columns is smaller than the default reference. I read somewhere that reactive statements do not work the datatable options. I attached a MWE.

rm(list=ls())
library(shiny)
library(datasets)
library(datatable)
DT<-data.table(matrix(abs(rnorm(100,sd=100000)),nrow=10))


server<-shinyServer(function(input, output) {

# Return the requested dataset
columns <- reactive({
switch(input$columns,
all= c("V1","V2","V3","V4","V5","V6","V7","V8","V9","V10"),
left= c("V1","V2","V3","V4","V5"),
right= c("V6","V7","V8","V9","V10"))
})


# Show table
output$view <- DT::renderDataTable(
format(DT[,.SD,.SDcols=columns()],digits = 0,scientific=F),
option=list(columnDefs=list(list(targets=0:(length(columns())-1), class="dt-right")))
)
})
library(shiny)

# Define UI for dataset viewer application
ui<-shinyUI(fluidPage(

# Application title
titlePanel("Shiny Text"),

# Sidebar with controls to select a dataset and specify the
# number of observations to view
sidebarLayout(
sidebarPanel(
selectInput("columns", label = h3("Select Columns"),
choices = list("All columns" = "all", "Left side" = "left",
"Right side" = "right"), selected = "all")
),

# Show a summary of the dataset and an HTML table with the
# requested number of observations
mainPanel(
DT::dataTableOutput("view")
)
)
))



runApp(list(ui=ui,server=server))

Answer

Datatable options are not reactive in the sense that you can't change the options without redrawing the entire table, but if you are willing to redraw the table then it isn't a problem see below:

If you change your server function to this it should work:

server<-shinyServer(function(input, output) {

  # Return the requested dataset
  columns <- reactive({
    switch(input$columns,
           all= c("V1","V2","V3","V4","V5","V6","V7","V8","V9","V10"),
           left= c("V1","V2","V3","V4","V5"),
           right= c("V6","V7","V8","V9","V10"))
  })

  # reactive datatable

  rdt <- reactive({
    DT::datatable(format(DT[,.SD,.SDcols=columns()],digits=0,scientific=FALSE),
                  option=list(columnDefs=list(
                    list(targets=seq_len(length(columns()))-1, 
                         class="dt-right"))))
  })


  # Show table
  output$view <- DT::renderDataTable(
    rdt()
    )

}) 

I am creating a reactive datatable that responds to columns() and redraws the table with the correct columnDef. If you had a lot of data this would be very slow.

Comments