Trivial Shiny question: build a list of names from user input

Shiny newbie here, struggling with a trivial problem.

Goal: Build a list of names from user input. Each time the user enters a name and clicks Save, append that name to a character vector of names, and update the output with the new contents of that vector.

Problem: Every time they click Save, the character vector has been reinitialized to an empty vector, so the first name is gone, and the new name they entered becomes the only contents of the vector.

ui <- fluidPage(
  fluidRow(
    textInput("name", "Name:"),
    actionButton("btnSave", "Save")
  ),
  fluidRow(
    h5("Output:"),
    verbatimTextOutput("out")
  )
)

server <- function(input, output, session) {
  nameList <- as.character(NULL)
  
  observeEvent(input$btnSave, {
    
    newList <- append(nameList, isolate(input$name))

    nameList <- reactive(newList)
    output$out <- renderPrint(nameList())
  })
}

Remember What Happens in Vegas Stays in Vegas ad? In R functions can be a lot like that; unless the return value is captured it goes out of scope as soon as the function completes. It's not persistent.

When trying to accumulate a list of return values of function, the trick is to create an object to receive in the global environment, not the local environment. Here's a toy example.

library(charlatan)
minions <- list()
assemble_cast <- function() sample(ch_name(1000),1)
for(i in 1:10) minions[i] = minions[1] = assemble_cast()
unlist(minions)
#>  [1] "Efren Mertz"          "Dorthea Auer"         "Millicent Kirlin"    
#>  [4] "Dr. Yamilet Bernier"  "Bailey Flatley-Howe"  "Jamil McKenzie PhD"  
#>  [7] "Kelley Sawayn"        "Latonia Torp-Kovacek" "Ms. Jonell Pouros"   
#> [10] "Efren Mertz"

So, are you saying that the nameList I'm referencing here

    newList <- append(nameList(), isolate(input$name))
    nameList <- reactive(newList)

... is local to the observeEvent handler? I thought that R would reference the one I defined in the outer scope (i.e., the server function).

If it’s in a function within a function it’s local to that function. If the inner function returns only to its parent function it stays in that local environment.

library(shiny)
ui <- fluidPage(
  fluidRow(
    textInput("name", "Name:"),
    actionButton("btnSave", "Save")
  ),
  fluidRow(
    h5("Output:"),
    verbatimTextOutput("out")
  )
)

server <- function(input, output, session) {
  
  nameList <- reactiveVal()
  
  observeEvent(input$btnSave, {
    nameList(append(nameList(), input$name))
  })
  
  output$out <- renderPrint(nameList())
  
}

shinyApp(ui = ui, server = server)
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.