Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Shiny DT datatable input reactivity after table is reloaded

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)))
      }
    })
  }
)

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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)))
      }
    })
  }
)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading