rshinydtshiny-reactivity

How to reset an output that depends on calculations over inputs?


I really had trouble finding a title for this question, hope it helps.

I have a fairly complex app for which I'm having trouble resetting an output after an actionButton ("Confirm" on this example) triggers the re-evaluation of a reactiveValues number that feeds a reactive table.

This causes that the selected table only renders once and no matter how many times the table that feeds it changes, it keeps showing the same result as the first time it was rendered.

It will be easy for you to see what I mean from this example. Believe me, it is the minimax from the one I'm coming from:

library(shiny)
library(DT)
 

ui <- fluidPage(
  DTOutput("table"),
  actionButton("checkvalues", "Check")
  
)

server <- function(input, output, session) {
  
  primedata <- reactiveValues(data = NULL)
  primedata$data <- as.numeric(Sys.time()) %% 10000 
  
  tabledata <- reactive({
    
    data <- data.frame(rep(primedata$data, 5))
    for (i in 1:5) {
      data$V1[i] <- as.character(selectInput(paste0("sel", i), "",
                                             choices = c("None selected" = 0,
                                                          "Icecream", "Donut"), 
                                                          selected = 0, width = "120px"))
  }
    return(data)
    })
  
  
  output$table <- renderDataTable( #Generar tabla
    
    tabledata(), filter = 'top', escape = FALSE, selection = 'none', server = FALSE,
    callback = JS("table.rows().every(function(i, tab, row) {
            var $this = $(this.node());
            $this.attr('id', this.data()[0]);
            $this.addClass('shiny-input-container');
          });
          Shiny.unbindAll(table.table().node());
          Shiny.bindAll(table.table().node());")
    
  )
  
  # helper function for reading inputs in DT
  shinyValue = function(id, len) { 
    unlist(lapply(seq_len(len), function(i) { 
      value = input[[paste0(id, i)]] 
      if (is.null(value)) NA else value 
    })) 
  }
  
  observeEvent(input$checkvalues, {
    
    datos <- tabledata()
    
      selected <- cbind(datos, data.frame(N = shinyValue("sel", nrow(datos)))) 
      selected <- selected %>% group_by(N) %>% summarise("see" = n())
    showModal(modalDialog(
      title = HTML('<h3 style="text-align:center;">Problem: this table will keep showing the same results as the first one presented</h3>'),
      renderDT(datatable(selected, options = list(dom = 't', ordering = F))),
      footer = actionButton("Confirm", "Confirm")))
    
  })
  
  observeEvent(input$Confirm, {
    
     primedata$data <- as.numeric(Sys.time()) %% 10000
      
     removeModal() 

    })
  
}

shinyApp(ui, server)

Solution

  • When you change primedata$data (by clicking on the Confirm button) this re-renders the table, and you have to unbind before:

    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());
            }
          })")
      )),
      DTOutput("table"),
      actionButton("checkvalues", "Check")
    )
    
    
      observeEvent(input$Confirm, {
        
        session$sendCustomMessage("unbindDT", "table")
        
        primedata$data <- as.numeric(Sys.time()) %% 10000
        
        removeModal() 
        
      })