I'm trying to change the width of some columns in a DT::datatable, unfortunately using the columnDefs option only appears to work when there are a small number of columns in the data.
When I add all the columns to my data the column widths no longer follow what I put in the columnDefs options.
Here is an example, as you can see the 1st table the width are all constant, whereas in the second table I have been able to manual set the widths as I desire. Removing the scrollX argument doesn't work either, and given the number of columns my data has I need it in there.
library(MASS)
library(shiny)
library(DT)
ui <- fluidPage(
mainPanel(
DT::dataTableOutput("table1"),
br(),
br(),
br(),
DT::dataTableOutput("table2")
)
)
server <- function(input, output) {
output$table1 <- DT::renderDataTable({
DT::datatable(
Cars93[,-(20:27)],
rownames = FALSE,
options = list(
pageLength = 5,
autowidth = TRUE,
scrollX = TRUE,
searching = TRUE,
ordering = TRUE,
paging = TRUE,
columnDefs = list(list(width = "200px", targets = c(0:2)),
list(width = "20px", targets = 3),
list(width = "50px", targets = 4))
)
)
})
output$table2 <- DT::renderDataTable({
DT::datatable(
Cars93[,-(6:27)],
rownames = FALSE,
options = list(
pageLength = 5,
autowidth = TRUE,
scrollX = TRUE,
searching = TRUE,
ordering = TRUE,
paging = TRUE,
columnDefs = list(list(width = "200px", targets = c(0:2)),
list(width = "20px", targets = 3),
list(width = "50px", targets = 4))
)
)
})
}
shinyApp(ui, server)
What do I need to change in my code to be able to set the column widths in the 1st table like I have them in the 2nd table while will having all the columns and scrollX?
Thanks
Try:
ui <- fluidPage(
tags$head(
tags$style(
HTML("table {table-layout: fixed;}")
)
),
......
and replace autowidth with autoWidth.
Related
I know you can use options to adjust width by hand. Something along the lines:
DT::datatable(mtcars,
options = list(
autoWidth = TRUE,
columnDefs = list(list(width = '70px',
targets = which(colnames(mtcars) %in% c("gear"))),
list(width = '100px',
targets = which(colnames(mtcars) %in% c("disp", "hp")))
)
)
)
I see no way to adjust the column width to fit content, without hardcoded values. I found a datatables function columns.adjust() which theoretically re-adjusts column width to input, but how to use it in R / R shiny?
MRE:
library(shiny)
library(DT)
ui <- fluidPage(
DT::dataTableOutput(outputId = "table")
)
server <- function(input, output) {
output$table <- DT::renderDataTable({
DT::datatable(mtcars,
options = list(
autoWidth = TRUE, # here we set fixed width. how to set depending on input?
columnDefs = list(list(width = '70px',
targets = which(colnames(mtcars) %in% c("gear"))),
list(width = '100px',
targets = which(colnames(mtcars) %in% c("disp", "hp")))
)
)
)
})
}
shinyApp(ui, server)
I am using the button colvis from the DT package to select which columns I would like to show in the table. Here you have more info about the button colvis.
It works perfectly fine, it hides the columns that I don't want to select and the result is shown to the user.
However, it seems that this info is not updated when I download the file.
If I only select "Petal.Width" and "Species":
Then, I download the file... and I open it. I still have all the columns and not the selected ones.
I have been trying to find a solution, but I haven't found anything.
Does anyone know how to fix it?
Thanks in advance.
Here is my code:
library(shiny)
library(DT)
ui <- fluidPage(
dataTableOutput("table")
)
server <- function(input, output, session) {
output$table <- renderDataTable({
datatable(
iris,
filter = list(position = 'top', clear = FALSE),
selection = "none", #this is to avoid select rows if you click on the rows
rownames = FALSE,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
dom = 'Blrtip',
buttons =
list(I('colvis'),'copy', 'print', list(
extend = 'collection',
buttons = list(
list(extend = 'csv', filename = paste0("iris"), title = NULL),
list(extend = 'excel', filename = paste0("iris"), title = NULL)),
text = 'Download'
)),
lengthMenu = list(c(10, 30, 50, -1),
c('10', '30', '50', 'All'))
),
class = "display"
)
})
}
shinyApp(ui, server)
library(DT)
datatable(
iris,
extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = list(
I("colvis"),
list(
extend = "collection",
text = "Download",
buttons = list(
list(
extend = "csv",
exportOptions = list(
columns = ":visible"
)
)
)
)
)
)
)
Thanks to Stéphane Laurent's answer, I managed to find an answer.
I had some problems to have both buttons (csv and excel) and how to organise the lists with the proposed solution, but I found the way to do it.
I will add the answer with the original code just in case someone has problems like me.
library(shiny)
library(DT)
ui <- fluidPage(
dataTableOutput("table")
)
server <- function(input, output, session) {
output$table <- renderDataTable({
datatable(
iris,
filter = list(position = 'top', clear = FALSE),
selection = "none", #this is to avoid select rows if you click on the rows
rownames = FALSE,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
dom = 'Blrtip',
buttons =
list(I('colvis'),'copy', 'print', list(
extend = 'collection',
text = 'Download',
buttons = list(
list(
extend = "csv", filename = paste0("iris"), title=NULL,
exportOptions = list(
columns = ":visible")
),
list(
extend = "excel", filename = paste0("iris"), title=NULL,
exportOptions = list(
columns = ":visible")
)
)
)),
lengthMenu = list(c(10, 30, 50, -1),
c('10', '30', '50', 'All'))
),
class = "display"
)
})
}
shinyApp(ui, server)
I have this piece of code. The DT datatable does not render at all. It shows the columns, and nothing else. I posted a related question earlier, but apparently, this issue needed to be posted as a separate question. I am.
Any idea of what I am missing?
library(dplyr)
library(shiny)
library(DT)
library(data.table)
mtcars <- mtcars[1:5, ]
ui <- fluidPage(
fluidRow(
dataTableOutput(('mtcarsDT')),
)
)
server <- function(input, output, session) {
output$mtcarsDT <- DT::renderDataTable({
recFeedbackCol <- lapply(1:nrow(mtcars), function(recnum)
as.character(
radioButtons(
paste0(
'rec', recnum),
'',
choices = c('good' = 'Good', 'bad' = 'Bad', 'neutral' = 'Neutral'),
inline = TRUE
)
)
)
recFeedbackCol <- tibble(feedback = recFeedbackCol)
mtcars <- bind_cols(
mtcars,
recFeedbackCol
)
mtcars %>%
DT::datatable(
extensions = 'FixedColumns',
rownames = FALSE,
escape = FALSE,
class="compact cell-border",
options = list(
pageLength = 15,
lengthChange = FALSE,
scrollX = TRUE,
searching = FALSE,
dom = 't',
ordering = TRUE,
fixedColumns = list(leftColumns = 2),
preDrawCallback = JS(
'function() { Shiny.unbindAll(this.api().table().node()); }'
),
drawCallback = JS(
'function() { Shiny.bindAll(this.api().table().node()); } '
),
autoWidth = TRUE,
columnDefs = list(
list(width = '200px', targets = ncol(mtcars))
)
)
)
})
}
shinyApp(ui = ui, server = server)
The problem seems to be targets parameter of columnDefs. It accepts column index starting from 0. To specify the last column, it needs to be reduced by 1.
columnDefs = list(
list(width = '200px', targets = ncol(mtcars) - 1)
)
The DT package in Shiny produces a table with a searchbar that searches over every column in the table. I have a column of metadata which I do not want to display in the table, but I still want the rows to come up if I search with the search bar.
For example, the app below contains a column titled searchCol . This column is just letters. I want to hide this column in the actual table, and I want to be able to search for the letter b , using the DT search bar, and have the second row show up.
Is there a way to hide the column but have it still work with the search bar?
library(shiny)
library(DT)
ui <- fluidPage(
DTOutput('tbl1'),
)
server <- function(input, output, session) {
output$tbl1 <- DT::renderDT(server = TRUE, {
datatable(
cbind(data.frame(replicate(3,sample(0:1,26,rep=TRUE))), data.frame(searchCol = letters)),
escape = FALSE,
rownames = FALSE,
filter = list(position = "top", clear = FALSE, plain = TRUE),
selection = "single",
options = list(
autoWidth = TRUE,
pageLength = 50,
lengthMenu = c(50, 100, 1000),
dom = 'Blfrtip',
buttons = c('copy', 'excel')
)
)
})
}
shinyApp(ui, server)
I've adapted the answer from here to the format you need to use in DT::datatable. You can use columnDefs to define the render options for the different columns, targets defines which column you mean. Please note that the JS library datatables starts counting columns at 0.
library(shiny)
library(DT)
ui <- fluidPage(
DTOutput('tbl1'),
)
server <- function(input, output, session) {
output$tbl1 <- DT::renderDT(server = TRUE, {
datatable(
cbind(data.frame(replicate(3,sample(0:1,26,rep=TRUE))), data.frame(searchCol = letters)),
escape = FALSE,
rownames = FALSE,
filter = list(position = "top", clear = FALSE, plain = TRUE),
selection = "single",
options = list(
autoWidth = TRUE,
pageLength = 50,
lengthMenu = c(50, 100, 1000),
dom = 'Blfrtip',
buttons = c('copy', 'excel'),
columnDefs = list(
list(
targets = 3,
searchable = TRUE,
visible = FALSE
)
)
)
)
})
}
shinyApp(ui, server)
I would like to change the language of a datatable on the fly
I have the following code
output$prr2 <- renderDataTable({
prr()}, options = list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2) ) ),
language = list(url = if(getLanguage()=='gr') '//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json' else
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json' ))
getLanguage() returns the value of selected_language, prr() returns a data.frame.
I want to do something like this in order to change options of the table after selecting a different language in a dropdown selected_language
proxy = dataTableProxy('prr2')
observeEvent(input$selected_language,{ replace language option of datatable prr2})
Any idea about this?
I can't test since you don't provide a reproducible example. I would try
output$prr2 <- renderDataTable({
prr()
}, options = exprToFunction(list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2))),
language = list(
url = ifelse(getLanguage()=='gr',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json')
)
)))
EDIT
output$prr2 <- renderDataTable({
datatable(
prr(),
options = exprToFunction(list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2))),
language = list(
url = ifelse(getLanguage()=='gr',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json')
)
)
)
)
})
EDIT 2
Full app which works:
library(shiny)
library(DT)
ui <- fluidPage(
radioButtons("language", "Language", choices = c("gr", "en")),
DTOutput("prr2")
)
server <- function(input, output, session){
output$prr2 <- renderDT({
datatable(
iris,
options = exprToFunction(list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2))),
language = list(
url = ifelse(input$language=='gr',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json')
)
))
)
})
}
shinyApp(ui, server)