Search code examples
shinyreactable

SliderInput in Reactable not working when rendered using renderUI


I want to use a sliderInput within a reactable table. As the dimensions are only known at runtime (depend on other user inputs), I need to create the table using renderUI.

When I create the reactable with sliderInput in the UI, everything is shown correctly (with the small caveat, that the HTML dependencies are missing due to me calling as.character on the sliderInput code, but this can be fixed by including another sliderInput somewhere or adding the dependencies manually).

However, when I render the reactable using renderUI, no sliderInput is shown, instead an empty <input> field is shown.

An MWE looks like this

library(shiny)
library(reactable)

df <- data.frame(
  x = 1,
  # as.character is needed to have the element in a data.frame,
  # but this removes the html_dependencies attribute...
  value = as.character(shiny::sliderInput("slider1", "Slider 1", 0, 10, 1))
)
df2 <- data.frame(
  x = 2,
  value = as.character(shiny::sliderInput("slider2", "Slider 2", 0, 10, 1))
)

ui <- fluidPage(
  h3("Table 1"),
  helpText("This does not work! -> Slider is not displayed!"),
  uiOutput("table"),
  
  sliderInput("slider3", "Slider 3", 0, 10, 1),
  h3("Table 2"),
  helpText("This works! (but only if we have another sliderInput somewhere, eg above)"),
  reactable(
    df2,
    columns = list(
      value = colDef(html = TRUE)
    )
  )
)

server <- function(input, output, session) {
  output$table <- renderUI({
    reactable(
      df,
      columns = list(
        value = colDef(html = TRUE)
      )
    )
  })
  
  observeEvent(input$slider1, {
    cat(sprintf("Slider 1: %s\n", input$slider1))
  })
  observeEvent(input$slider2, {
    cat(sprintf("Slider 2: %s\n", input$slider2))
  })
  observeEvent(input$slider3, {
    cat(sprintf("Slider 3: %s\n", input$slider3))
  })
}

shinyApp(ui, server)
#> Slider 2: 1
#> Slider 3: 1
#> Slider 2: 7
#> Slider 3: 2
#> Slider 3: 6

ex image

As you can see, Table 2 is rendered correctly and slider 2 and 3 are also working correctly, while Table 1 (using renderUI) with slider 1 is neither rendered correctly nor is the input registered correctly.


Solution

  • One possible solution that I found, which is not using reactable but flextable, is this:

    library(shiny)
    library(kableExtra)
    
    deps <- shiny::span()
    attr(deps, "html_dependencies") <- attr(shiny::sliderInput("_", NULL, 0, 0, 0), "html_dependencies")
    
    ui <- fluidPage(
      deps,
      uiOutput("table")
    )
    
    df <- data.frame(
      x = 1,
      value = as.character(shiny::sliderInput("slider1", "Slider 1", 0, 10, 1))
    )
    
    server <- function(input, output, session) {
      output$table <- renderText({
        df |> 
          kbl("html", escape = FALSE) %>%
          kable_styling(
            bootstrap_options = c("striped", "hover", "condensed")
          )
      })
      
      observeEvent(input$slider1, {
        cat(sprintf("Slider 1: %s\n", input$slider1))
      })
      
    }
    
    shinyApp(ui, server)