Вопрос или проблема
Я выявил проблему с DT (стабильная: 0.33, dev: 0.33.1) для R Shiny (1.9.1), которую можно решить с помощью Javascript.
В частности, при использовании нескольких вкладок (см. репрекс ниже), если использовать DT::replaceData()
для обновления таблицы DT с прокруткой на другом наборе вкладок, первый рендер будет корректным:
Но при втором нажатии на кнопку заголовки “сжимаются” вместе с левой стороны:
Это, похоже, является проблемой только тогда, когда включена любая форма прокрутки (что в данном случае является обязательной функциональностью), независимо от того, используется ли расширение прокрутки (и пагинация) или нет. Неиспользование прокрутки не приводит к этому поведению.
Спасибо за любую помощь, которую вы можете предоставить.
Репрекс:
library(shiny)
library(DT)
# не работает
ui = fluidPage(
tabsetPanel(
tabPanel("кнопка",
actionButton("change", "Изменить")
),
tabPanel("таблица",
DT::dataTableOutput("table"))
)
)
# работает
# ui = fluidPage(
#
# tabsetPanel(
# tabPanel("кнопка и таблица в одной вкладке",
# tags$br(),
# actionButton("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="Выбрать видимые столбцы")
),
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)
Ответ или решение
Проблема с перемещением заголовков колонок в DT при использовании replaceData() в Shiny
Как IT-эксперт, я хотел бы подробно рассмотреть возникшую вами проблему с перемещением заголовков колонок в таблице DT при использовании функции replaceData()
в приложении R Shiny. Данная проблема происходит при работе с несколькими вкладками и включает в себя особенности использования скроллинга, что делает её достаточно уникальной.
Описание проблемы
Вы столкнулись с тем, что при обновлении данных в таблице DT на одной вкладке, а самом обновлении происходит с другой вкладки, заголовки колонок «сжимаются» на первом обновлении, а затем на втором клике. Эта проблема возникает только при использовании скроллинга; без него заголовки отображаются корректно.
Данная ситуация была продемонстрирована в вашем коде с использованием библиотеки shiny
и DT
.
Технический анализ
-
Скроллинг: Использование скроллинга в таблице DT с последующим изменением данных, находясь на другой вкладке, может привести к некорректному распределению элементов на экране. В данном случае, после первого клика таблица корректно обновляется, но во время второго клика заголовки теряют своё нормальное размещение. Это может быть связано с тем, как скрипты JavaScript обрабатывают изменение данных в контексте вкладок.
-
Строка с новым значением: При каждом изменении данных через
replaceData()
, библиотека DT может не корректно обновлять стили CSS, которые влияют на ширину и размещение заголовков. Это связано с тем, что вкладка, на которой вы пытаетесь обновить данные, не является активной, и события связанные со стилями могут не инициализироваться должным образом.
Решение
Одним из решений является принудительное обновление стилей таблицы после замены данных, что можно сделать с помощью JavaScript. Вы можете добавить JavaScript код через tags$script()
, который будет принудительно вызывать пересчет размеров колонок после выполнения replaceData()
. Например:
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")
# Принудительное обновление таблицы
session$sendCustomMessage("recalcTable", list(tableId = 'table'))
})
А также добавить в UI следующий JavaScript код:
tags$script(HTML("
Shiny.addCustomMessageHandler('recalcTable', function(message) {
var table = $('#' + message.tableId).DataTable();
table.columns.adjust().responsive.recalc();
});
"))
Заключение
Решение этой проблемы требует обращения к комбинации R и JavaScript. Принудительное обновление размеров колонок после изменения данных может решить вашу проблему с неправильным отображением заголовков. Такого рода подход, хотя и требует дополнительных усилий на первом этапе, в итоге обеспечит стабильное и предсказуемое поведение вашего приложения.
Оставляйте комментарии или задавайте вопросы, если вам потребуется дальнейшая информация или помощь по данной проблеме.