rshinyreactive-programmingdt

Shiny DT appearance messed up when selected rows used as reactive values


The tables displayed through the DataTables interface from DT package appear messy (e.g. disordered elements, strange looking pagination ...) when using reactive values which their input come from the rows selected in the first table. Using R version 3.4.3, and shiny 1.1.0 and DT 0.4 which both are sourced from CRAN.

The minimal code:

library(shiny)
library(DT)

ui <- fluidPage(
  DT::dataTableOutput("dt"),
  actionButton("go", "Go"),
  wellPanel(DT::dataTableOutput("selected"))
)

server <- function(input, output, session) {
  output$dt <-  DT::renderDataTable({
    DT::datatable(
      mtcars,
      style = 'bootstrap',
      filter = 'top',
      rownames = FALSE,
      extensions = 'Buttons',
      selection = list(mode = 'single'),
      options = list(
        pageLength = 10,
        dom = '<"top"ifl>t<"bottom"Bp>',
        buttons = c('copy', 'csv', 'excel'),
        searchHighlight = TRUE
      )
    )
  })

  rv <- reactiveValues(val = FALSE)
  observeEvent(input$go, {
    rv$val <- input$go
  })
  observeEvent(input$dt_rows_selected, {
    rv$val <- FALSE
  })

  output$selected <- DT::renderDataTable({
    if (rv$val == FALSE)
      return()

    reactive({
      validate(need(input$dt_rows_selected != "", "Select a row."))
      mtcars[input$dt_rows_selected, ]
    }) -> .mtcars

    isolate({
      DT::datatable(
        .mtcars(),
        style = 'bootstrap',
        filter = 'top',
        rownames = FALSE,
        extensions = 'Buttons',
        selection = list(mode = 'single'),
        options = list(
          pageLength = 10,
          dom = '<"top"ifl>t<"bottom"Bp>',
          buttons = c('copy', 'csv', 'excel'),
          searchHighlight = TRUE
        )
      ) -> table
    })
    table
  })

}

shinyApp(ui, server)

It looks decent without the second table:


Solution

  • The issue is caused by the part style = 'bootstrap' which does not work well with return(NULL). Replacing if (rv$val == FALSE) return() with req(rv$val) in the output has solved the problem. Has taken the reference here.