1

I encountered an unexpected behavior. What I intend to do is: - when users click "Select All," all rows in "Summary Table" get selected. This WORKS. However, the code below doesn't get called.

data <- eventReactive(input$selectAll,{
      print("Select All - restore data")
      rawdata

  })

- on the other hand, when users click "Deselect All," all rows in "Summary Table" get deselected. This WORKS and the code below GETS called.

# Restore data when users click 'Deselect All'
  data <- eventReactive(input$deselectAll,{
      print("Deselect All - restore data")
      rawdata
  })

Any idea why?

Here is my full code:

DATASET

colA <- c('A','B','C','D','E')
colB <- c(1,2,3,4,5)
rawdata <- as.data.frame(cbind(colA,colB))
View(rawdata)

server.R

function(input, output, session) {

  # Activate tab 'Result' when users click 'Run'
  observeEvent(input$runButton, {
      updateTabsetPanel(session, "allResults", 'result')
  })

  # Create a dataset based on users' selected variables
  data <- eventReactive(input$inputVars_rows_selected,{
      print("Select Some Vars")
      rawdata[, c(input$inputVars_rows_selected)]
  })

  # Restore data when users click 'Select All'
  data <- eventReactive(input$selectAll,{
      print("Select All - restore data")
      rawdata
  })

  # Restore data when users click 'Deselect All'
  data <- eventReactive(input$deselectAll,{
      print("Deselect All - restore data")
      rawdata
  })

  ### VARIABLE SELECTION ####

  var <- reactiveValues()

  # Select all vars
  observeEvent(input$selectAll,{
      print("SelectAll ObserveEvent")
      var$selected <- 1:nrow(rawdata)
      print(var$selected)
  })

  # Deselect all vars
  observeEvent(input$deselectAll,{
      print("deselectAll ObserveEvent")
      var$selected <- 0
      print(var$selected)
      print(data())
  })

  ### RESULT TAB ###

  result <- eventReactive (input$runButton, {
      head(data(),2)
  })

  ### RENDERING FUNCTIONS ###

  # Default SummaryTable
  output$inputVars <- DT::renderDataTable({
      if (input$selectAll==0 & input$deselectAll==0) {
          print("Default Summary Table")
          DT::datatable(rawdata, options = list(paging = FALSE, searching = FALSE))
      } 
      else {
          DT::datatable(rawdata, options = list(paging = FALSE, searching = FALSE), selection = list(target = 'row', selected = var$selected))
      }
  })

  # Display results
  output$result <- DT::renderDataTable({
      DT::datatable(result(), options = list(paging = FALSE, searching = FALSE))
  })

  output$temp <- renderPrint({
      print(input$selectAll)
      print(input$deselectAll)
  })
}

ui.R

fluidPage(

  sidebarPanel(
      actionButton("runButton", strong("Run!"))
  ),

  mainPanel(
      tabsetPanel(id = "allResults",
        tabPanel(value='inputVars',title='Variable Selection', 
                  verticalLayout(
                      DT::dataTableOutput('inputVars'),
                      br(),
                      fluidRow(align="bottom", 
                             column(2, actionButton("selectAll"  , strong("Select All"))),
                             column(3, actionButton("deselectAll", strong("Deselect All")))
                      )
                  )
                ),
        tabPanel(value='result',title='Result', DT::dataTableOutput('result')),
        tabPanel(value='temp',title="TEMP", verbatimTextOutput("temp"))
      )
  )

)

UPDATED Server.R #2: @Mike and @HubertL, I think you are right: the issue is caused by eventReactive having cached values. In this updated version, observeEvent corresponding to Select All and Deselect All work as expected. However, now eventReactive corresponding to input$inputVars_rows_selected NEVER gets called. Any idea why?

function(input, output, session) {

  # Activate tab 'Result' when users click 'Run'
  observeEvent(input$runButton, {
    updateTabsetPanel(session, "allResults", 'result')
  })

  data <- reactiveValues()

  # Create a dataset based on users' selected variables
   data <- eventReactive(input$inputVars_rows_selected,{
       print("Select Some Vars")
       print(input$inputVars_rows_selected)
       rawdata[, c(input$inputVars_rows_selected)]
  })


  ### VARIABLE SELECTION ####

  var <- reactiveValues()

  # Select all vars
  observeEvent(input$selectAll,{
    print("SelectAll ObserveEvent")
    data <- rawdata
    var$selected <- 1:nrow(rawdata)
    print(var$selected)
    print(data)

  })

  # Deselect all vars
  observeEvent(input$deselectAll,{
    print("deselectAll ObserveEvent")
    data <- rawdata
    var$selected <- 0
    print(var$selected)
    print(data)

  })

  ### RESULT TAB ###

  result <- eventReactive (input$runButton, {
    head(data(),2)
  })

  ### RENDERING FUNCTIONS ###

  # Default SummaryTable
  output$inputVars <- DT::renderDataTable({
    if (input$selectAll==0 & input$deselectAll==0) {
      print("Default Summary Table")
      DT::datatable(rawdata, options = list(paging = FALSE, searching = FALSE))
    } 
    else {
      DT::datatable(rawdata, options = list(paging = FALSE, searching = FALSE), selection = list(target = 'row', selected = var$selected))
    }
  })

  # Display results
  output$result <- DT::renderDataTable({
    DT::datatable(result(), options = list(paging = FALSE, searching = FALSE))
  })

  output$temp <- renderPrint({
    print(input$selectAll)
    print(input$deselectAll)
    print(input$inputVars_rows_selected)

  })
}
Ketty
  • 811
  • 10
  • 21
  • A name has one object : You cannot assign several reactive functions to a same variable name, only the last assignment is taken into account here. Consider making a single eventReactive function, and use if statements to return a different selection according to input – HubertL May 27 '17 at 20:54
  • Oddly that does not seem to be true... – Mike Wise May 27 '17 at 20:56
  • Probably is true actually, but hard to tell which `data()` is being pulled from because of `eventReactive` caching. – Mike Wise May 27 '17 at 21:08

2 Answers2

1

One reason is because eventReactive is "lazily-evaluated" as opposed to observeEvent which is evaulated immediately.

So in your case the observeEvent corresponding to deselectAll actually uses data(), so that reactiveEvent gets triggered.

  # Deselect all vars
  observeEvent(input$deselectAll,{
    print("deselectAll ObserveEvent")
    var$selected <- 0
    print(var$selected)
    print(data())
  })

But the observeEvent corresponding to selectAll does not use data(), so that reactiveEvent does not get triggered:

  # Select all vars
  observeEvent(input$selectAll,{
    print("SelectAll ObserveEvent")
    var$selected <- 1:nrow(rawdata)
    print(var$selected)
  })

I suggest the following changes

  • If you add a print(data()) here you get some of the behavior you are seeking.

  • But it is still not completely right because HubertL's comment that one definition of data is being overwritten is also valid - and note that it is not easy to tell where it the data is being pulled. This is because eventReactive have cached values, so your print may not show up if a cached value is being used - your code need be executed to pull that data().

  • So in any case I would certainly suggest using different names (and more descriptive) than just repeating "data" to avoid confusion.

  • Also there is no need to use an eventReactive here, you probably want a simple reactive. eventReactive is usually needed if you want to avoid "reactions" from all the other reactive variables in the code, and I don't see a need for that here.

  • I would also recommend putting rawdata into a reactiveValues something like this: rv <- reactiveValues(rawdata=rawdata) and then using it as rv$rawdata. This makes it reactive, and then something that uses it will be triggred and recomputed if it ever changes.

See this link (observeEvent vs. eventReactive) for a discussion of the "laziness" of those commands.

Mike Wise
  • 22,131
  • 8
  • 81
  • 104
  • if I add "print(data())" in the observeEvent corresponding to selectAll, the reactiveEvent still does not get triggered. I put my updated code in my original post. Thanks! – Ketty May 28 '17 at 02:21
  • Oddly, I never got a notification of this comment. Just saw it now. I will have a look at it later this evening or tomorrow morning. – Mike Wise May 29 '17 at 15:22
1

Below is the code that works. @Mike and @HubertL were right. The reason is because reactive is lazy vs observeEvent is not. Thanks all for your help!

function(input, output, session) {

  # Activate tab 'Result' when users click 'Run'
  observeEvent(input$runButton, {
    updateTabsetPanel(session, "allResults", 'result')
  })  

  data <- reactive({
     print("Select Some Vars")
     print(input$inputVars_rows_selected)
     rawdata[input$inputVars_rows_selected,]
  })

  ### VARIABLE SELECTION ####

  var <- reactiveValues()

  # Select all vars
  observeEvent(input$selectAll,{
    print("SelectAll --- ObserveEvent")
    var$selected <- 1:nrow(rawdata)
    print(var$selected)
    print(input$inputVars_rows_selected)
  })

  # Deselect all vars
  observeEvent(input$deselectAll,{
    print("deselectAll --- ObserveEvent")
    var$selected <- 0
    print(var$selected)
  })

  ### RESULT TAB ###

  result <- eventReactive (input$runButton, {
    head(data(),5)
  })

  ### RENDERING FUNCTIONS ###

  # Default SummaryTable
  output$inputVars <- DT::renderDataTable({
    if (input$selectAll==0 & input$deselectAll==0) {
      print("Default Summary Table")
      DT::datatable(rawdata, options = list(paging = FALSE, searching = FALSE))
    } 
    else {
      DT::datatable(rawdata, options = list(paging = FALSE, searching = FALSE), selection = list(target = 'row', selected = var$selected))
    }
  })

  # Display results
  output$result <- DT::renderDataTable({
    DT::datatable(result(), options = list(paging = FALSE, searching = FALSE))
  })

  output$temp <- renderPrint({
    print(input$selectAll)
    print(input$deselectAll)
    print(input$inputVars_rows_selected)

  })
}
Ketty
  • 811
  • 10
  • 21