rshiny

Modify values of a reactive DataFrame in Shiny


I am trying to build a Shiny app in which the user can "look up" rows in a data frame, and a reactive data frame records the count of how many times the user has looked up a each. My strategy is to append a column "n" (initially a column of 0's) to the data frame, and increment the "n" value of the appropriate observation by 1 each time that it is specified by the user. However, I have not found a way to implement such a reactive data frame.

I've attached the relevant code below. In my case, the user specifies a row in the data frame using the variables "id", and "dob". The "test" variable and the if/else statement is simply a safeguard to ensure that the user-specified observation actually exists in the data frame. "flag" is the name of my reactive data frame. The value of "n" should increment every time the user interacts with the "input$randomize" action button.

The error that I typically receive reads "Warning: Error in <-: invalid (NULL) left side of assignment."

I've searched through the related posts, but could not find one that satisfactorily addresses my situation. I hope I've explained things adequately. Please ask any questions where I've been unclear. Thanks in advance.

library(shiny)
library(tidyverse)
library(magrittr)

df <- read_csv("/filepath")
df <- add_column(n = 0)

server <- function(input, output) {
  flag <- reactiveVal({df})
  
  # Data transformation function
  dataTransform <- bindEvent(reactive({
    test = nrow(filter(flag(), id == input$id & dob == input$dob))
    
    if (test == 0){
      return(NULL)
    }
    else {
      flag()[flag()$id == input$id & flag()$dob == input$dob, "n"] %<>%
        + 1

        flag() %>%
        filter(id == input$id & dob == input$dob) %>%
        select(id, dob, kit_id, n) %>%
        return()
      }
    }), input$randomize
  )

Solution

  • The issue is that the way you are trying to update your reactiveVal will not work, i.e. to update your reactive value flag you have to use flag(NEW_VALUE), e.g. something like

    flag(mutate(flag(), n = ifelse(id == input$id & dob == input$dob, n + 1, n)))
    

    should work.

    Using a minimal reprex based on mtcars and without any filters:

    library(shiny)
    library(tidyverse)
    
    df <- mtcars
    df <- add_column(df, n = 0)
    
    ui <- fluidPage(
      actionButton("randomize", "click"),
      tableOutput("table")
    )
    
    server <- function(input, output, session) {
      flag <- reactiveVal(df)
      
      # Data transformation function
      dataTransform <- reactive({
        test = nrow(flag())
        
        if (test == 0) {
          return(NULL)
        }
        else {
          # Update reactive value
          flag(mutate(flag(), n = n + 1))
          
          flag()
        }
      }) %>%
        bindEvent(input$randomize)
      
      output$table <- renderTable({
        dataTransform()
      })
    }
    
    shinyApp(ui, server)
    #> 
    #> Listening on http://127.0.0.1:6810
    

    enter image description here