Как я могу улучшить свой код для создания динамического элемента пользовательского интерфейса? - PullRequest
0 голосов
/ 31 мая 2019

У меня есть динамический элемент Shiny 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)

Есть ли лучший способ написать это?

Обратите внимание, что в приведенном выше примере значения и метки являются произвольными.

Ответы [ 2 ]

0 голосов
/ 31 мая 2019

Ответ от @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)
0 голосов
/ 31 мая 2019

Вы можете использовать lapply() для создания нескольких (похожих) элементов пользовательского интерфейса на основе выбора пользователя.

Замените свой сервер следующим:

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