0

My Shiny app contains a DT datatable with a selectInput. The first time the table loads, I can obtain the selectInput value when it changes. However, when the table is reloaded by the user, I am no longer able to obtain the updated selectInput value. One solution would be to rename the selectInput inputId each time the table is reloaded and keep track of the inputId. I came across this post ('Reset inputs' button in shiny app) and hoped that a similar approach would work. Here, I put my DT datatable in a div with an id that is updated each time the table is reloaded. However, it does not work. In my example below, the user reloads the table by clicking "Reload table". After the table is reloaded, input$id1 no longer responds to the dropdown selection in the table. Any suggestions other than renaming the selectinput inputId each time the table is reloaded?

require(shiny)
require(DT)

shinyApp(
  ui = fluidPage(
    actionButton(inputId = "reload", label = "Reload table"),
    uiOutput("resettable_table")
  ),
  server = function(input, output, session) {
    rv <- reactiveValues(times = 1)
    observeEvent(input$reload, {
      rv$times <- rv$times + 1
    })
    output$mytable <- DT::renderDataTable({
      input$reload
      DT::datatable(
        data = data.frame(
          Col1 = as.character(selectInput(
            inputId = "id1",
            label = NULL,
            choices = letters
          ))
        ),
        escape = F,
        selection = "none",
        options = list(
          preDrawCallback = JS('function(){Shiny.unbindAll(this.api().table().node());}'),
          drawCallback = JS('function(){Shiny.bindAll(this.api().table().node());}')
        )
      )
    })
    
    output$resettable_table <- renderUI({
      req(rv$times)
      div(
        id = paste0("mydiv", rv$times),
        DT::dataTableOutput("mytable")
      )
    })
    
    observe({
      if(is.null(input$id1)) {
        print("input$id1 is NULL")
      } else {
        print(paste(c("input$id1:", input$id1)))
      }
    })
  }
)
Ben Ernest
  • 445
  • 3
  • 14

1 Answers1

0

One has to unbind before reloading. But, and I don't know why, one also has to set server = FALSE in renderDT:

shinyApp(
  ui = fluidPage(
    tags$head(tags$script(
      HTML(
        "Shiny.addCustomMessageHandler('unbindDT', function(id) {
            var $table = $('#'+id).find('table');
            if($table.length > 0){
              Shiny.unbindAll($table.DataTable().table().node());
            }
          })")
    )),
    actionButton(inputId = "reload", label = "Reload table"),
    uiOutput("resettable_table")
  ),
  server = function(input, output, session) {
    rv <- reactiveValues(times = 1)
    
    observeEvent(input$reload, {
      session$sendCustomMessage("unbindDT", "mytable")
      rv$times <- rv$times + 1
    })
    
    output$mytable <- DT::renderDataTable({
      input$reload
      DT::datatable(
        data = data.frame(
          Col1 = as.character(selectInput(
            inputId = "id1",
            label = NULL,
            choices = letters,
            selectize = FALSE
          ))
        ),
        escape = F,
        selection = "none",
        options = list(
          preDrawCallback = JS('function(){Shiny.unbindAll(this.api().table().node());}'),
          drawCallback = JS('function(){Shiny.bindAll(this.api().table().node());}')
        )
      )
    }, server = FALSE)
    
    output$resettable_table <- renderUI({
      req(rv$times)
      div(
        id = paste0("mydiv", rv$times),
        DT::dataTableOutput("mytable")
      )
    })
    
    observe({
      if(is.null(input$id1)) {
        print("input$id1 is NULL")
      } else {
        print(paste(c("input$id1:", input$id1)))
      }
    })
  }
)
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • That works, thanks! I saw that you suggested this approach in several other places on stackoverflow but I didn't think to try it in combination with what I had tried here. Much appreciated. – Ben Ernest Nov 29 '22 at 01:04
  • I posted another question but this time using reactive data for the table (https://stackoverflow.com/questions/74615616/shiny-dt-datatable-selectinput-with-reactive-data). The selectInput reactivity is lost when I use reactive data in the table and the data are updated. Any help would be greatly appreciated. – Ben Ernest Nov 29 '22 at 14:34