Заголовки столбцов Shiny DT перемещаются при переходе на другую вкладку, используя replaceData()?

Вопрос или проблема

Я выявил проблему с 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.

Технический анализ

  1. Скроллинг: Использование скроллинга в таблице DT с последующим изменением данных, находясь на другой вкладке, может привести к некорректному распределению элементов на экране. В данном случае, после первого клика таблица корректно обновляется, но во время второго клика заголовки теряют своё нормальное размещение. Это может быть связано с тем, как скрипты JavaScript обрабатывают изменение данных в контексте вкладок.

  2. Строка с новым значением: При каждом изменении данных через 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. Принудительное обновление размеров колонок после изменения данных может решить вашу проблему с неправильным отображением заголовков. Такого рода подход, хотя и требует дополнительных усилий на первом этапе, в итоге обеспечит стабильное и предсказуемое поведение вашего приложения.

Оставляйте комментарии или задавайте вопросы, если вам потребуется дальнейшая информация или помощь по данной проблеме.

Оцените материал
Добавить комментарий

Капча загружается...