I've identified an issue with DT (stable: 0.33, dev: 0.33.1) for R Shiny (1.9.1) that might be resolvable through some Javascript.
Specifically, when using multiple tabs (see reprex below) if using DT::replaceData()
to update a DT table with scroller on a different tabset from where a button is clicked, the first render will be correct:
But the second time the button is clicked, the headers "squish" together on the left-hand side:
This only seems to be an issue when any form of scrolling is enabled (which in this case, is the mandatory functionality) regardless of whether the scroller extension (and pagination) is used or not. Not using the scroller does not result in this behavior.
Reprex:
library(shiny)
library(DT)
# doesn't work
ui = fluidPage(
tabsetPanel(
tabPanel("button",
actionButton("change", "Change")
),
tabPanel("table",
DT::dataTableOutput("table"))
)
)
# works
# ui = fluidPage(
#
# tabsetPanel(
# tabPanel("button and table in one tab",
# tags$br(),
# actionButton("change", "Change"),
# tags$br(),
# DT::dataTableOutput("table"))
# )
#
# )
server = function(input, output, session) {
cars_plus = mtcars
cars_plus$new = sample(100, 1)
rvs = reactiveValues(
cars = cars_plus
)
table_proxy = DT::dataTableProxy("table")
output$table = DT::renderDataTable(server = T, {
DT::datatable(isolate(rvs$cars),
rownames = FALSE,
extensions = c('Buttons'),
options=list(
buttons = list(
list(extend = 'colvis', text = 'Choose visible columns')
),
dom = '<"top"B>rt<"bottom">i',
scrollY = '200',
paging = F
)
)
})
observeEvent(input$change,{
dat = rvs$cars
changer = sample(100, 1)
dat[3, "new"] = changer
rvs$cars = dat
DT::replaceData(table_proxy, dat, rownames = F, resetPaging = F, clearSelection = "none")
})
}
shinyApp(ui, server)
There are some issues with scrollY
. You can avoid this by adding an event handler on shown.bs.tab
which resets the width
of the dataTable
to 100%
and calls columns.adjust()
:
$(document).ready(function() {
$('a[data-toggle="tab"]').on( 'shown.bs.tab', function (e) {
$($.fn.dataTable.tables( true ) ).css('width', '100%');
$($.fn.dataTable.tables( true ) ).DataTable().columns.adjust().draw();
});
});
library(shiny)
library(DT)
ui = fluidPage(
tags$head(tags$script(HTML(
"$(document).ready(function() {
$('a[data-toggle=\"tab\"]').on( 'shown.bs.tab', function (e) {
$($.fn.dataTable.tables( true ) ).css('width', '100%');
$($.fn.dataTable.tables( true ) ).DataTable().columns.adjust().draw();
});
});"
))),
tabsetPanel(
tabPanel("button",
actionButton("change", "Change")
),
tabPanel("table",
DT::dataTableOutput("table"))
)
)
server = function(input, output, session) {
cars_plus = mtcars
cars_plus$new = sample(100, 1)
rvs = reactiveValues(
cars = cars_plus
)
table_proxy = DT::dataTableProxy("table")
output$table = DT::renderDataTable(server = T, {
DT::datatable(isolate(rvs$cars),
rownames = FALSE,
extensions = c('Buttons'),
options=list(
buttons = list(
list(extend = 'colvis', text = 'Choose visible columns')
),
dom = '<"top"B>rt<"bottom">i',
scrollY = '200',
paging = F
)
)
})
observeEvent(input$change,{
dat = rvs$cars
changer = sample(100, 1)
dat[3, "new"] = changer
rvs$cars = dat
DT::replaceData(table_proxy, dat, rownames = F, resetPaging = F, clearSelection = "none")
})
}
shinyApp(ui, server)