Search code examples
rdatatablepopupshinyaction-button

R Shiny: Click Button Within Datatable to Display Popup Twice in a row


Using RStudio 1.0.136 and R Shiny 0.14.2, I am trying to create a data table that has an action button on each row, and when a button is clicked a popup will appear. My code is currently working, except you cannot click the same button twice in a row. I have posted 2 versions of example code below:

library(shiny)
library(DT)
library(shinyBS)

shinyApp(
ui <- fluidPage(
DT::dataTableOutput("data"),

uiOutput("modal")
),

server <- function(input, output,session) {

shinyInput <- function(FUN, len, id, ...) {
  inputs <- character(len)
  for (i in seq_len(len)) {
   inputs[i] <- as.character(FUN(paste0(id, i), ...))
 }
  inputs
}

df <- reactiveValues(data = data.frame(
  Assessment = shinyInput(actionButton, 10, 'button_', label = "Assessment", onclick = 'Shiny.onInputChange(\"select_button\",  this.id)' ),
  Value1 = 1:10,
  Value2 = c("A", "B", "C", "D", "E"),
  stringsAsFactors = FALSE,
  row.names = 1:10
))

output$data <- DT::renderDataTable(
  df$data, server = FALSE, escape = FALSE, selection = 'none'
)


observeEvent(input$select_button, {
    s <- as.numeric(strsplit(input$select_button, "_")[[1]][2])
   output$modal <- renderUI({
tagList(
bsModal(paste('model', s ,sep=''), "Assessment", "select_button", size = "small",
          textAreaInput("text", label = h3("Enter Assessment") , value = "", width = "100%", height = "200px", resize = "none"),
           actionButton("Enter", "Enter")
   ))
     })
  toggleModal(session,paste('model', s ,sep=''), toggle = "Assessment")

})      
})

The second code is:

library(shiny)
library(DT)
library(shinyBS)

shinyApp(
ui <- fluidPage(
DT::dataTableOutput("data"),
bsModal("modalnew", "Assessment", "select_button", size = "small",
        textAreaInput("text", label = h3("Enter Assessment") , value = "",        width = "100%", height = "200px", resize = "none"),
        actionButton("Enter", "Enter")
)

),

server <- function(input, output,session) {

shinyInput <- function(FUN, len, id, ...) {
  inputs <- character(len)
  for (i in seq_len(len)) {
   inputs[i] <- as.character(FUN(paste0(id, i), ...))
 }
  inputs
}

df <- reactiveValues(data = data.frame(
  Assessment = shinyInput(actionButton, 10, 'button_', label = "Assessment", onclick = 'Shiny.onInputChange(\"select_button\",  this.id)' ),
  Value1 = 1:10,
  Value2 = c("A", "B", "C", "D", "E"),
  stringsAsFactors = FALSE,
  row.names = 1:10
))

output$data <- DT::renderDataTable(
  df$data, server = FALSE, escape = FALSE, selection = 'none'
)

observeEvent(input$select_button, {
  s <- as.numeric(strsplit(input$select_button, "_")[[1]][2])
  toggleModal(session, "modalnew", toggle = "close")
})   
})

What is entered in the popups is currently irrelevant. Any suggestions on how to allow the same button to be clicked twice in a row would be greatly appreciated.


Solution

  • I have modified your code. I have used a js function from this link to reset the value of select_button.

    library(shiny)
    library(DT)
    library(shinyBS)
    
    
    shinyApp(
      ui <- fluidPage(
    
        shinyjs::useShinyjs(),
        #js function to reset a button, variableName is the button name whose value we want to reset
        tags$script("Shiny.addCustomMessageHandler('resetInputValue', function(variableName){
                    Shiny.onInputChange(variableName, null);
                    });
                    "),
        DT::dataTableOutput("data"),
    
        uiOutput("modal")
      ),
    
      server <- function(input, output,session) {
    
        shinyInput <- function(FUN, len, id, ...) {
          inputs <- character(len)
          for (i in seq_len(len)) {
            inputs[i] <- as.character(FUN(paste0(id, i), ...))
          }
          inputs
        }
    
        df <- reactiveValues(data = data.frame(
          Assessment = shinyInput(actionButton, 10, 'button_', label = "Assessment", onclick = 'Shiny.onInputChange(\"select_button\",  this.id)' ),
          Value1 = 1:10,
          Value2 = c("A", "B", "C", "D", "E"),
          stringsAsFactors = FALSE,
          row.names = 1:10
        ))
    
        output$data <- DT::renderDataTable(
          df$data, server = FALSE, escape = FALSE, selection = 'none'
        )
    
    
        observeEvent(input$select_button, {
          s <- as.numeric(strsplit(input$select_button, "_")[[1]][2])
          output$modal <- renderUI({
            tagList(
              bsModal(paste('model', s ,sep=''), "Assessment", "select_button", size = "small",
                      textAreaInput("text", label = h3("Enter Assessment") , value = "", width = "100%", height = "200px", resize = "none"),
                      actionButton("Enter", "Enter")
              ))
          })
          toggleModal(session,paste('model', s ,sep=''), toggle = "Assessment")
          ##Reset the select_button
          session$sendCustomMessage(type = 'resetInputValue', message =  "select_button")
        })      
      })
    

    Hope it helps!