1

I have a bit of renderUI code that created numeric input boxes and populates them from a list. it looks like this:

  output$Small1A <- renderUI({
    numericInput("Small1A","",min = 0, max = 100, value = Reduction()$Reduction[Reduction()$Category == "Small1A"])
    })

Reduction() is a list that is preloaded with some default values or can be loaded from a file. It looks like this

Category Reduction
Small1A  0.5
Small2A  0.5
...
Medium3D 0.5
...
Huge7E  7.4

there are 140 Elements (Small, Medium, Large, Huge) 1-7 and A-E

these are grouped on the UI as 5 collapsible boxes each with a 4x7 grid in.

 column(1, offset = 1, uiOutput("Small1A")),
 column(1, offset = 0, uiOutput("Small2A")),
(and so)

It seems like I should be able to replace the 140 renderUI statements with something neater, given the regularity of the source. How would you do this?

DX101
  • 148
  • 11
  • 1
    Perhaps this helps. https://stackoverflow.com/a/58468059/7669809 – www Dec 20 '19 at 15:43
  • 1
    Try to use `lapply` and a customized function for all these repetitive elements. – www Dec 20 '19 at 15:44
  • 1
    There's almost certainly a better way with something like what @www suggests. But without seeing what you're working on I'm just gonna ask: do you really need and want so many inputs? It seems like a really overwhelming UI – camille Dec 20 '19 at 15:49
  • Also, if there's a pattern to these, consider using shiny modules for some abstraction. – SmokeyShakers Dec 20 '19 at 15:54
  • The inputs can be loaded from an external file and then tweaked by the user for sensitivity adjustment. They are all all necessary. – DX101 Dec 20 '19 at 16:01
  • Ultimately I replaced the numericInputs with matrixInput()s from the shinyMatrix library, so I had 5 4x7 matricies instead of 140 numericInputs. – DX101 Jan 03 '20 at 11:56

1 Answers1

1

Here is an approach using lapply as suggestef in the comments. I am using some dummy data to show how you'd combine lapply with a custom numericInput function.

library(shiny)

some_values <- data.frame(Names = LETTERS[1:10], Values = seq(1, 100, 10))

make_num_in <- function(val) {
  numericInput(
    paste("in", val, sep = "_"),
    paste("in", val, sep = "_"),
    min = 0,
    max = 100,
    value = some_values[some_values$Names == val, "Values"]
  )
}

ui <- basicPage(
  column(5,
  actionButton("show1", "show 1"),
  uiOutput("box1"),
  actionButton("show2", "show 2"),
  uiOutput("box2")
  ),
  column(5,
        textOutput("input_A"),
        textOutput("input_F")
         )
)

server <- function(input, output, session) {
  observeEvent(input$show1, {
    output$box1 <-
      renderUI({
        tagList(lapply(LETTERS[1:5], make_num_in))
      })
  })

  observeEvent(input$show2, {
    output$box2 <-
      renderUI({
        tagList(lapply(LETTERS[6:10], make_num_in))
      })
  })

  output$input_A <- renderText(paste("input A is: ", input[["in_A"]]))
  output$input_F <- renderText(paste("input F is: ", input[["in_F"]]))

}

shinyApp(ui, server)
teofil
  • 2,344
  • 1
  • 8
  • 17