8
votes

I am trying to create a table using Shiny, where the user can click on a row in order to see further information about that row. I thought I understood how to do this (see code attached).

However, right now as soon as the user clicks the "getQueue" action button, the observeEvent(input$fileList_cell_clicked, {}) seems to get called. Why would this be called before the user even has the chance to click on a row? Is it also called when the table is generated? Is there any way around this?

I need to replace "output$devel <- renderText("cell_clicked_called")" with code that will have all sorts of errors if there isn't an actual cell to refer to.

Thank you for any advice!

ui <- fluidPage(
   actionButton("getQueue", "Get list of queued files"),
   verbatimTextOutput("devel"),
   DT::dataTableOutput("fileList")     
)

shinyServer <- function(input, output) {
   observeEvent(input$getQueue, {
   #get list of excel files
   toTable <<- data.frame("queueFiles" = list.files("queue/", pattern = "*.xlsx")) #need to catch if there are no files in queue
   output$fileList <- DT::renderDataTable({
     toTable
   }, selection = 'single') #, selection = list(mode = 'single', selected = as.character(1))
   })
   observeEvent(input$fileList_cell_clicked, {
     output$devel <- renderText("cell_clicked_called")
   })}

shinyApp(ui = ui, server = shinyServer)

minimal error code

1

1 Answers

7
votes

DT initializes input$tableId_cell_clicked as an empty list, which causes observeEvent to trigger since observeEvent only ignores NULL values by default. You can stop the reactive expression when this list is empty by inserting something like req(length(input$tableId_cell_clicked) > 0).

Here's a slightly modified version of your example that demonstrates this.

library(shiny)

ui <- fluidPage(
  actionButton("getQueue", "Get list of queued files"),
  verbatimTextOutput("devel"),
  DT::dataTableOutput("fileList")     
)

shinyServer <- function(input, output) {

  tbl <- eventReactive(input$getQueue, {
    mtcars
  })

  output$fileList <- DT::renderDataTable({
    tbl()
  }, selection = 'single')

  output$devel <- renderPrint({
    req(length(input$fileList_cell_clicked) > 0)
    input$fileList_cell_clicked
  })
}

shinyApp(ui = ui, server = shinyServer)