简体   繁体   中英

How to store previous states of reactive variables in R Shiny application?

Let's imagine a Shiny app that generates a vector of 10 random words when the user clicks on an ActionButton. These words are presented in a table (DT package) that allows the user to select the words/rows he is interested in in order to build a selection. This selection is transferred to another table (using "_rows_selected" input from DT datatable) and displayed. This is what the minimal example below does:

library(shiny)
library(DT)

ui <- fluidPage(
  actionButton("generate", "New random words"),
  h5("Original data"),
  dataTableOutput("results"),
  br(),
  h5("Selected data"),
  dataTableOutput("selection")
)

server <- function(input, output, session) {
  
  generated_data <- eventReactive(input$generate, {
    random_words <- sapply(1:10, function(x) sample(letters, x) %>% paste(collapse=""))
    data.frame(ID=1:10, Word=random_words)
  })
  
  output$results <- renderDataTable(
    datatable(generated_data(), rownames = FALSE)
  )
  
  output$selection <- renderDataTable(
    generated_data()[input$results_rows_selected,] %>%
      datatable(rownames=FALSE)
  )
}

shinyApp(ui, server)

However, if the user clicks the actionbutton again, new words are generated and the selection in the second table is therefore deleted. I would like the selection to keep track of previously selected words and add any new selection of words we have selected.

How can I do this? How can I keep in memory the previous states of my reactive variable (frozen at the time of the generation of new words with a new click) and concatenate them to its currently selected words?

I haven't found a solution so far, thank you in advance for your help!

You can store them in a reactive value, like this:

all_words <- reactiveVal(data.frame(ID = integer(0), Word = character(0)))

generated_data <- eventReactive(input$generate, {
  random_words <- 
    sapply(1:10, function(x) sample(letters, x) %>% paste(collapse=""))
  dat <- data.frame(ID=1:10, Word=random_words)
  all_words(rbind(all_words(), dat))
  dat
})

By adapting a little bit the code proposed by Stéphane Laurent, I can propose this complete app that corresponds perfectly to what I wanted and what I had in mind when I asked my question. It is possible that there is a more concise solution, in particular concerning the variables dat and all_words .

library(shiny)
library(DT)

ui <- fluidPage(
  actionButton("generate", "New random words"),
  h5("Original data"),
  dataTableOutput("results"),
  br(),
  h5("Selected data"),
  dataTableOutput("selection")
)

server <- function(input, output, session) {
  
  all_words <- reactiveVal(data.frame(ID = integer(0), Word = character(0)))
  dat <- data.frame(ID=integer(0), Word=character(0))
  
  generated_data <- eventReactive(input$generate, {
    all_words(rbind(all_words(), dat[input$results_rows_selected,]))
    random_words <- 
      sapply(1:10, function(x) sample(letters, x) %>% paste(collapse=""))
    dat <<- data.frame(ID=1:10, Word=random_words)
    dat
  })
  
  output$results <- renderDataTable(
    datatable(generated_data(), rownames = FALSE)
  )
  
  output$selection <- renderDataTable(
    rbind(generated_data()[input$results_rows_selected,], all_words()) %>%
      datatable(rownames=FALSE)
  )
}

shinyApp(ui, server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM