使用 renderUI() 更新动态 UI 后提取输入小部件的值

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

我已经通过 renderUI() 成功地动态更新了 UI。我有一长串输入可供选择。复选框用于动态添加数字输入。因此,为了实现这一点,我使用了 lapply。但是,我在 checkboxgroup 本身中使用选定复选框的值来填充动态添加的数字输入的 ID,而不是在 lapply.

中使用 paste(input, i)

ui 代码片段:

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")

服务器代码片段:

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
    })
  })

我已经使用 input[[x[i]]] 来实例化在添加或删除数字输入后要保留的值。但是,我想将 input$x[i]input[[x[i]]] 中的值提取到向量中以供进一步使用,但我无法做到。

*ERROR:Must use single string to index into reactivevalues

感谢任何帮助。


编辑

使用 3 种不同的方式从输入中提取值会产生 3 种不同的错误: 使用 print(input$x[i]) # ERROR

NULL
NULL
NULL
NULL
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

使用print(input[[x[i]]]) # ERROR

Must use single string to index into reactivevalues

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

invalid subscript type 'language'

如果我没理解错的话,您想访问动态生成的小部件的值,然后将它们打印出来。

在我下面的例子中,应该很容易概括,选择是 iris 数据集中变量 Setosa 的水平。

生成的小部件的 ID 始终由 checkboxGroupInput 中选定的值给出。因此,input$checkboxgrp 表示应该为 setosa 的哪个级别生成一个小部件。同时 input$checkboxgrp 给出生成的小部件的 ID。这就是为什么您不需要将 "active" 小部件的 ID 存储在其他变量 x 中(这可能是一个反应值)。

要打印出这些值,您可以执行以下操作:

 output$value <- renderPrint({

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

这一行 print(input[[x[i]]]) ## ERROR 会产生错误,因为 x[i](无论它是什么)不是具有单个值但具有 多个 值的向量。


完整示例:

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)

编辑:

您可以稍微调整 lapply 部分(注意 <<- 运算符 :))

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

编辑 2 回复评论:

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())
  })

}