1
votes

I want to collect user inputs, and output them as a table/data frame within Shiny. Inspired by the post here (Collect All user inputs throughout the Shiny App), I was able to do this but with some issues below. Here I have attached the example code, where I intend to collect the user input using the reactive textInput box. The number of textInput boxes is according to the user input for "Number of box". The output table looks fine when I kept increasing the "Number of box", such as I increased the number of boxes from 1 to 2 (see attached screenshot 1 and 2). However, when I changed the number of boxes from 2 back to 1, the output table still showed the previous results "textBox2 the second input" (see screenshot 3). My question is how to remove this previous input ("textBox2 the second input") and only print out the current user input. Thanks!

Example code

library(shiny)
ui <- basicPage(
  fluidRow(column(6,
           numericInput("nbox", "Number of box", value = 1, 
                        min = 1))),
  fluidRow(column(6,style='padding:0px;',
                  wellPanel(
                    uiOutput("textInputBox"))), 
           column(6, style='padding:0px;',
                  tableOutput('show_inputs')))
)

server <- shinyServer(function(input, output, session){
  
  output$textInputBox <- renderUI({
    num <- as.integer(input$nbox)
    lapply(1:num, function(i) {
      textInput(paste0("textBox", i),
                label = paste0("textBox", i))
      })
    })

  AllInputs <- reactive({
    myvalues <- NULL
    for(i in 1:length(names(input))){
      myvalues <- as.data.frame(rbind(myvalues,
                                      (cbind(names(input)[i],input[[names(input)[i]]]))))
    }
    names(myvalues) <- c("User input variable","User input value")
    myvalues
  })
  
  output$show_inputs <- renderTable({
    AllInputs()
    })
  
})
shinyApp(ui = ui, server = server)

Screen shot (1,2,3 in order) screenshot_1 screenshot_2 screenshot_3

1

1 Answers

0
votes

Created inputs are not deleted when a new renderUI is called, so there is no solution this way.

A workaround is to use a counter (like the one previously used to create the input) and use it to rebuild the names:

AllInputs <- reactive({
    num <- as.integer( input$nbox )
    my_names <- paste0("textBox", 1:num)
    all_values <- stack( reactiveValuesToList(input) )
    myvalues <- all_values[ all_values$ind %in% c("nbox", my_names), 
                            c(2, 1)]
    names(myvalues) <- c("User input variable","User input value")
    myvalues
})

Note the use of reactiveValuesToList to replace the loop.