Reputation: 127
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!
Upvotes: 2
Views: 791
Reputation: 127
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)
Upvotes: 1
Reputation: 84519
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
})
Upvotes: 2