Search code examples
rshinyreactiver6

R Shiny: Update a R6 Object on different actionButtons


I am trying to build a shiny update that allows the user to update a R6 Class object by clicking different actionButtons, as shown in the example below.

I also looked into different options such as using reactiveValues etc, but I cannot get it to work properly.

library(shiny)
library(R6)

DataInfo <- R6Class(
  classname = "DataInfo",
  public = list(
    data1 = NULL,
    data2 = NULL,
    initialize = function() {},
    AddData1 = function(data1 = NA) {
      self$data1 <- data1
    },
    AddData2 = function(data2 = NA) {
        self$data2 <- data2
    }
  )
)

ui <- fluidPage(
  actionButton("add_data1_btn", "Add Data1"),
  actionButton("add_data2_btn", "Add Data2"),
  verbatimTextOutput("output")
)

server <- function(input, output, session) {
  my_info <- DataInfo$new()
  
  observeEvent(input$add_data1_btn, {
    my_info$AddData1(data1 = "Sample data1")
  })
  
  observeEvent(input$add_data2_btn, {
    my_info$AddData2("Sample data2")
  })
  
  output$output <- renderPrint({
    list(
      data1 = my_info$data1,
      data2 = my_info$data2

    )
  })
}

shinyApp(ui, server)

How can I get my app to react to changes in my_data?


Solution

  • Initially, I thought wrapping my_info in a reactiveValues would work, but it didn't.

    An easy solution is simply to add references to the two buttons in your renderPrint.

    [By the way, if you put a print(my_info) in each of your button observers, you'll see that my_info does update, but the app doesn't realise that it has. So the answer to your question "Is there a way how I can make the DataInfo object reactive to the input so it updates its state?" is that "It already does". So what I think you meant to ask is "How can I get my app to react to changes in my_info?". That's a subtle but important difference.]

    library(shiny)
    library(R6)
    
    DataInfo <- R6Class(
      classname = "DataInfo",
      public = list(
        data1 = NULL,
        data2 = NULL,
        initialize = function() {},
        AddData1 = function(data1 = NA) {
          self$data1 <- data1
        },
        AddData2 = function(data2 = NA) {
          self$data2 <- data2
        }
      )
    )
    
    ui <- fluidPage(
      actionButton("add_data1_btn", "Add Data1"),
      actionButton("add_data2_btn", "Add Data2"),
      verbatimTextOutput("output")
    )
    
    server <- function(input, output, session) {
      my_info <- DataInfo$new()
      
      observeEvent(input$add_data1_btn, {
        my_info$AddData1(data1 = "Sample data1")
      })
      
      observeEvent(input$add_data2_btn, {
        my_info$AddData2("Sample data2")
    
      })
      
      output$output <- renderPrint({
        input$add_data1_btn
        input$add_data2_btn
        list(
          data1 = my_info$data1,
          data2 = my_info$data2
        )
      })
    }
    
    shinyApp(ui, server)