ok1more
ok1more

Reputation: 900

Using input from a dynamically created input in shiny

I am trying to create a dynamic UI that has variable number of user inputs based on a user input and charts that uses that second level of user input.

A working example below:

library(shiny)


ui <- fluidPage(

titlePanel("Old Faithful Geyser Data"),
    numericInput(inputId = "Chartcount",
        label = "Enter number of charts",
        value = 5,
        min = 2,
        max = 8),
       uiOutput("distui")
    )


server <- function(input, output) {

c_count = reactive({input$Chartcount})
output$distui <- renderUI({
    lapply(seq(1:c_count()), function(x){ 
    chartId = (paste("Chart",x, sep = "="))
    sinput <- sliderInput(inputId = paste(x,"_bins"),
                    "Number of bins:",
                    min = 1,
                    max = 50,
                    value = 30)
    
    
    selectedbins = input[[paste(x,"_bins")]] # input$inputId does not work here as expression after $ can not be evaluated
    
    x    <- faithful[, 2]
    bins <- seq(min(x), max(x), length.out = 25 ) #I want to use selectedbins here for length.out

    distplot <- renderPlot(hist(x, breaks = bins, col = 'darkgray', border = 'white'))
    list(chartId, sinput,selectedbins, distplot)
    
    })
})

}

shinyApp(ui = ui, server = server)

I think there are at least a couple of problems with this.

  1. Selected number of bins resets as soon as they are selected

  2. I get an error when I try to use selectedbins in the chart for length.out

    bins <- seq(min(x), max(x), length.out = selectedbins ) # This throws an error Error: argument 'length.out' must be of length 1

Upvotes: 0

Views: 71

Answers (1)

Geovany
Geovany

Reputation: 5687

The selected number of bins is resetting because it is inside of the same reactive expression, you should put it in a different reactive expression, otherwise the full expression is going to be executed every time you change the input and it is going to recreate all the inputs and plots.

The second problem is caused because you are trying to use the selectedbins input value before the slider is created, therefore the value is NULL (length 0), you can only get the value after the slider is created.

Below is your code modified to create the plots in a separated reactive expression as a nested expression, maybe not the best solution but it is in the same style that your program. Also, reusing the x variable is confusing, so I changed the first one by k.

library(shiny)

ui <- fluidPage(
  titlePanel("Old Faithful Geyser Data"),
  numericInput(inputId = "Chartcount",
               label = "Enter number of charts",
               value = 5,
               min = 2,
               max = 8),
  uiOutput("distui")
)

server <- function(input, output) {
  
  output$distui <- renderUI({
    lapply(seq(1:input$Chartcount), function(k){ 
      chartId = (paste("Chart", k, sep = "="))
      sinput <- sliderInput(inputId = paste(k, "bins_"),
                            "Number of bins:",
                            min = 1,
                            max = 50,
                            value = 30)
      x <- faithful[, 2]
     
      distplot <- tagList(
        renderUI({
          selectedbins = input[[paste(k, "bins_")]]
          bins <- seq(min(x), max(x), length.out = selectedbins )
          tagList(
            selectedbins,
            renderPlot(hist(x, breaks = bins, col = 'darkgray', border = 'white'))
          )
        })
      )
      
      list(chartId, sinput, distplot)
      
    })
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 2

Related Questions