rstudio / DT

R Interface to the jQuery Plug-in DataTables
https://rstudio.github.io/DT/
Other
597 stars 182 forks source link

Wide datatables causing scrollx to scroll back when applying filters #915

Open mihirp161 opened 3 years ago

mihirp161 commented 3 years ago

I am able to render a datatable in my shiny app. However, whenever there is a wide table, the horizontal scroller gets back to it's initial position when you apply filters on the columns in the back. This issue occurs with numeric columns only.

I was wondering if there is a way I can disable range-based filters (but keep the filter boxes themselves) or if there is any other workaround for this problem. Not sure if this is a bug.

I have looked at issues #599 , #461, #554, and #698. They do not provide a workaround unfortunately.

Here is a reproducible example along with pictures-

options(scipen = 99999) #converts the sci numbers to their regular format
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinythemes)
library(writexl)
library(dplyr)
library(DT)
library(dplyr)

mtcars_modified <- mtcars %>% dplyr::mutate(wt_2= wt,
                                            qsec_2 = qsec,
                                            am_2= am,
                                            mpg_2= mpg,
                                            gear_2 = gear,
                                            carb_2 = carb,
                                            disp_2 = disp,
                                            row_names_col= rownames(mtcars))

ui <- fluidPage(

  theme = shinythemes::shinytheme("simplex"),

  shinyjs::useShinyjs(), # enables javascript/jQuery enhanchments

  # Create Right Side Text
  navbarPage( 

    id = "navbar",
    title= div(HTML("G<em>T</em>")),
    #windowTitle = "GT",

    tabPanel("Data Set Info",

             materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
                            value = TRUE, status = "warning"),
             sidebarLayout(
               # radio/action buttons
               sidebarPanel(

                 id = "Sidebar",

                 prettyRadioButtons(
                   inputId = "controller",
                   label = "Choose:", 
                   choices = c("About"= 1,
                               "iris"= 2,
                               "mtcars_modified" = 3),
                   icon= icon("check"),
                   selected = 1,
                   status = "success",
                   animation="smooth"
                 ),

                 br(),
                 br()
               ),

               #panel where output is shown from server
               mainPanel(
                 id = "main_panel",

                 tabsetPanel(
                   id = "hidden_tabs",
                   type = "hidden",
                   tabPanelBody(
                     "panel1", "navigation"
                   ),

                   tabPanelBody(
                     "panel2", 
                     tabsetPanel(
                       tabPanel("Data", DT::DTOutput('panel1_data')),
                       tabPanel("Summary", verbatimTextOutput("panel1_sum")),
                       tabPanel(
                         "Plot"
                       )
                     )
                   ),
                   tabPanelBody(
                     "panel3",
                     tabsetPanel(
                       tabPanel("Data", DT::DTOutput('panel3_data')),
                       tabPanel("Summary", verbatimTextOutput("panel3_sum")),
                       tabPanel(
                         "Plot"
                       )
                     )
                   )
                 )
               )
             )
    ) ,
    #resizes the navbar tabs/button
    tags$head(tags$style(HTML('.navbar-brand {width: 270px; font-size:35px; text-align:left;
                              font-family: "serif";')))
  )
)

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

  # this event hides the side panel when toggled on/off
  observeEvent(input$toggleSidebar, {
    shinyjs::toggle(id = "Sidebar", condition = input$toggleSidebar)
    if(!isTRUE(input$toggleSidebar)) {
      shinyjs::runjs("$('#main_panel').removeClass('col-sm-8').addClass('col-sm-12')")
    } else {
      shinyjs::runjs("$('#main_panel').removeClass('col-sm-12').addClass('col-sm-8')")
    }

  })

  # here we put all the data
  data_sets <- list(df1 = data.frame(), 
                    df2= iris, 
                    df3 = mtcars_modified)

  # store current dataset in reactive so we can work with plot panels
  data_to_use <- reactiveValues(name = "df", data = data.frame())

  observeEvent(input$controller, {

    # skip first panel since it is used to display navigation
    updateTabsetPanel(session, inputId= "hidden_tabs", selected = paste0("panel", input$controller))

    # enswure value is avilable throught selected tabSet
    req(input$controller)

    # get current data and df name
    data_to_use$data <- data_sets[[as.numeric(input$controller)]]
    data_to_use$name <- names(data_sets[as.numeric(input$controller)])

    # update table and sum
    output[[paste0('panel',  input$controller, '_data')]] <- 
    DT::renderDT(server = FALSE, {
    DT::datatable(data_to_use$data,
                  filter = 'top',
                  extensions = 'Buttons',
                  options = list(scrollY = 600,
                                 scrollX = TRUE,
                                 dom = '<"float-left"l><"float-right"f>rt<"row"<"col-sm-4"B><"col-sm-4"i><"col-sm-4"p>>',
                                 lengthMenu=  list(c(10, 25, 50, -1),
                                                   c('10', '25', '50','All')),
                                 buttons = list(
                                   list(extend = "collection", text = "Download",
                                        filename = "data_excel",
                                        exportOptions = list(
                                          modifier = list(page = "all")
                                        ),
                                        action = DT::JS("function ( e, dt, node, config ) {
                                  Shiny.setInputValue('Download_DATA', true, {priority: 'event'});}"
                                        )
                                   )
                                 ),
                                 scrollCollapse= TRUE,
                                 lengthChange = TRUE,
                                 widthChange= TRUE,
                                 rownames = TRUE))})

    output[[paste0('panel',  input$controller, '_sum')]] <- renderPrint(summary(data_to_use$data))

  })

}

#runs the app
shinyApp(ui= ui, server= server)

Annotation 2021-04-27 155926

Annotation 2021-04-27 171142


By filing an issue to this repo, I promise that

I understand that my issue may be closed if I don't fulfill my promises.

mihirp161 commented 3 years ago

react-table doesn't have the native button feature :( And my app is heavily dependent on this package's functionality.

philibe commented 3 years ago

Hello @opendatasurgeon Maybe there are paths of workarounds in this not closed issue: #769.

Because nearly all of my datatables are very wide, I don't have ScrollX=TRUE anymore. I workarounded everywhere by a pure css solution like it is described in the related issue.

mihirp161 commented 3 years ago

Thanks @philibe . Thanks for your help! Appreciate it :)

erifa1 commented 2 years ago

Hi, I'm having the same issue. I'm interested by any ideas! Thanks