rshinydynamic-ui

Extracting values of input widgets after updating dynamic UI using renderUI()


I have successfully updated UI dynamically through renderUI(). I have a long list of inputs to choose from. The check boxes are used to dynamically add numeric inputs. So, to implement this, I used lapply. However, I have used values of selected check boxes in checkboxgroup itself to populate IDs of the dynamically added numerical input instead of using paste(input, i) in lapply.

ui code snippet :

checkboxGroupInput(inputId = "checkboxgrp", label = "Select types",
                       choices = list("ELECTAPP","NB W $","PUR","MANUAL LTR","REDEMPTION","NB W TRANSFER","NB WOUT $","OUTPUT")),
...    
fluidRow(column(12, verbatimTextOutput("value")))
...
uiOutput("numerics")

server code snippet :

renderUI({
    numInputs <- length(input$checkboxgrp)

    if(numInputs==0){
      wellPanel("No transaction selected")
    }
    else{
      lapply(1:numInputs, function(i){
        x[i]=input$checkboxgrp[i]
        list(numericInput(input$checkboxgrp[i], min = 0, label = input$checkboxgrp[i], 
                         value= input[[x[i]]] ))
      })
    }
  })
  output$value <- renderPrint({
    numInputs <- length(input$checkboxgrp)
    lapply(1:numInputs, function(i){
      print(input[[x[i]]]) ## ERROR
    })
  })

I have used input[[x[i]]] as to instantiate value to be retained after adding or removing a numeric input. But, I want to extract values from input$x[i] or input[[x[i]]] into a vector for further use which I'm unable to do.

*ERROR:Must use single string to index into reactivevalues

Any help is appreciated.


EDIT

using 3 different ways of extracting values from input generate 3 different errors: Using print(input$x[i]) # ERROR

NULL
NULL
NULL
NULL
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

Using print(input[[x[i]]]) # ERROR

Must use single string to index into reactivevalues

Using print('$'(input, x[i])) # ERROR

invalid subscript type 'language'

Solution

  • If I understand you correctly, you want to access values of dynamically generated widgets and then just print them out.

    In my example below, which should be easy to generalise, the choices are the levels of the variable Setosa from the iris dataset.

    The IDs of the generated widgets are always given by the selected values in checkboxGroupInput. So, input$checkboxgrp says to shiny for which level of setosa there should be generated a widget. At the same time input$checkboxgrp gives IDs of generated widgets. That's why you don't need to store the IDs of "active" widgets in other variable x (which is probably a reactive value).

    To print the values out you can do the following:

     output$value <- renderPrint({
    
         activeWidgets <- input$checkboxgrp
         for (i in activeWidgets) {
           print(paste0(i, " = ", input[[i]]))
         }
       })
    

    This line print(input[[x[i]]]) ## ERROR yields an error because x[i] (whatever it is) is not a vector with a single value but with multiple values.


    Full example:

    library(shiny)
    
    ui <- fluidPage(
    
       titlePanel("Old Faithful Geyser Data"),
    
       sidebarLayout(
          sidebarPanel(
             checkboxGroupInput("checkboxgrp", "levels", levels(iris$Species))
          ),
          mainPanel(
            fluidRow(
              column(6, uiOutput("dynamic")),
              column(6, verbatimTextOutput("value"))
            )
          )
       )
    )
    
    server <- function(input, output) {
    
       output$dynamic <- renderUI({
    
         numInputs <- length(input$checkboxgrp)
    
         if(numInputs==0){
           wellPanel("No transaction selected")
         }
         else{
           lapply(1:numInputs, function(i){
             x[i]=input$checkboxgrp[i]
             list(numericInput(input$checkboxgrp[i], min = 0, label = input$checkboxgrp[i], 
                               value= input[[x[i]]] ))
           })
         }
       })
    
       output$value <- renderPrint({
    
         activeWidgets <- input$checkboxgrp
         for (i in activeWidgets) {
           print(paste0(i, " = ", input[[i]]))
         }
       })
    
    }
    
    
    shinyApp(ui = ui, server = server)
    

    Edit:

    You could tweak the lapply part a little bit (mind <<- operator :) )

     else{
           activeWidgets <- input$checkboxgrp
           val <- 0
           lapply(activeWidgets, function(i){
             val <<- val + 1
             list(numericInput(i, min = 0, label = i, 
                               value = val ))
           })
         }
    

    Edit 2 In response to a comment:

    server <- function(input, output) {
    
      output$dynamic <- renderUI({
    
        numInputs <- length(input$checkboxgrp)
    
        if(numInputs==0){
          wellPanel("No transaction selected")
        }
          else{
            activeWidgets <- input$checkboxgrp
            val <- 0
            lapply(activeWidgets, function(i){
              val <<- val + 1
              list(numericInput(i, min = 0, label = i, 
                                value = val ))
            })
          }
      })
    
      allChoices <- reactive({
        # Require that all input$checkboxgrp and 
        # the last generated numericInput are available.
        # (If the  last generated numericInput is available (is not NULL),
        # then all previous are available too)
    
        # "eval(parse(text = paste0("input$", input$checkboxgrp))))" yields
        # a value of the last generated numericInput. 
    
        # In this way we avoid multiple re-evaulation of allChoices() 
        # and errors
        req(input$checkboxgrp, eval(parse(text = paste0("input$", input$checkboxgrp))))
    
        activeWidgets <- input$checkboxgrp
        res <- numeric(length(activeWidgets))
        names(res) <- activeWidgets
        for (i in activeWidgets) {
          res[i] <- input[[i]]
    
        }
        res
      })
    
      output$value <- renderPrint({
        print(allChoices())
      })
    
    }