【问题标题】:How can I improve my code for generating a dynamic UI element?如何改进生成动态 UI 元素的代码?
【发布时间】:2019-10-17 10:32:35
【问题描述】:

我有一个动态闪亮的 UI 元素,提示用户从下拉列表中选择一个数字 (1-4)。然后 Shiny 通过生成我的程序将使用的相应数量的 numericInput() 元素进行响应。

以下代码有效,但它非常冗长,我想有一些方法可以改进代码以 (1) 使其更简洁,以及 (2) 避免使用 if/else 语句。

library(shiny)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("num", label = h3("Select box"), 
                  choices = list("Choice 1" = 1, "Choice 2" = 2, "Choice 3" = 3,
                                 "Choice 4" = 4), 
                  selected = 1),
      uiOutput("input_ui")
    ),
    mainPanel(
      tableOutput("table")
    )
  )
)

server <- function(input, output) {

  output$input_ui <- renderUI({
    num <- as.integer(input$num)
    if (num == 1) {
      fluidRow(
        column(6, numericInput("min", h5("Min"), value = 10)))
    } else if (num == 2) {
      fluidRow(
        column(6, numericInput("min", h5("Min"), value = 10)),
        column(6, numericInput("max", h5("Max"), value = 15))
      )
    } else if (num == 3) {
      fluidRow(
        column(6, numericInput("min", h5("Min"), value = 10)),
        column(6, numericInput("max", h5("Max"), value = 15)),
        column(6, numericInput("max", h5("Max"), value = 20))
      )
    } else if (num == 4) {
      fluidRow(
        column(6, numericInput("min", h5("Min"), value = 10)),
        column(6, numericInput("max", h5("Max"), value = 15)),
        column(6, numericInput("max", h5("Max"), value = 20)),
        column(6, numericInput("max", h5("Max"), value = 25))
      )
    }
  })
}

shinyApp(ui = ui, server = server)

有没有更好的写法?

请注意,在上面,值和标签是任意的。

【问题讨论】:

    标签: r user-interface shiny reactive


    【解决方案1】:

    您可以使用lapply() 根据用户的选择创建多个(相似的)UI 元素。

    用这个替换你的服务器:

    server <- function(input, output) {
    
      output$input_ui <- renderUI({
        req(input$num)
        if (as.numeric(input$num) > 1) {
        lapply(1:(as.numeric(input$num)-1), function(i) {
          numericInput(paste0("max",i), 
                       label=paste0("Max", i),
                       value = (i+2)*5)
        })
        }
      })
    }
    

    【讨论】:

      【解决方案2】:

      @phalteman 的回答很好。另一种方法是完全删除服务器端代码,这有其自身的好处。

      我们编写了一个函数来创建一个输入标签列表,并使用一个条件面板来检测正在选择哪个输入。

      library(shiny)
      
      multiple_numeric_input <- function(names){
        taglst = tagList()
        for (name in names){
          taglst = tagAppendChild(taglst,column(6,numericInput(name,name,value = 10)))
        }
        return(fluidRow(taglst))
      }
      
      ui <- fluidPage(
        sidebarLayout(
          sidebarPanel(
            selectInput("num", label = h3("Select box"), 
                        choices = list("Choice 1" = 1, "Choice 2" = 2, "Choice 3" = 3,
                                       "Choice 4" = 4), 
                        selected = 1),
            conditionalPanel("input.num == 1",
                             multiple_numeric_input(c("min"))),
            conditionalPanel("input.num == 2",
                             multiple_numeric_input(c("min","max"))),
            conditionalPanel("input.num == 3",
                             multiple_numeric_input(c("min","max","min2"))),
            conditionalPanel("input.num == 4",
                             multiple_numeric_input(c("min","max","min2","max2")))
          ),
          mainPanel(
            tableOutput("table")
          )
        )
      )
      
      server <- function(input, output) {}
      
      shinyApp(ui = ui, server = server)
      

      【讨论】:

      • 很好地使用了 UI 端函数来创建输入。以前没见过,如果你在服务器上有很多其他事情,它似乎特别有用......
      猜你喜欢
      • 1970-01-01
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 2011-09-07
      • 2018-09-24
      • 2018-05-29
      • 1970-01-01
      • 2010-12-17
      相关资源
      最近更新 更多