3

When running the below "MWE code using renderUI", in R studio console I get the message "Error in :: argument of length 0" though the App keeps working correctly. This MWE reflects a simple adaptation from the below "MWE code this was adapted from without renderUI" where renderUI isn't used, and this MWE doesn't show any type of error.

What could be causing this error? I need renderUI.

MWE code using renderUI:

 library(shiny)
    library(tidyverse)
    library(ggplot2)
    
    ui <- fluidPage(
      sidebarLayout(sidebarPanel(uiOutput("panel")),
      mainPanel(plotOutput("plot")),
    ))
    
    server <- function(input, output, session) {
      
      output$panel <- renderUI({
        tagList(
          sliderInput('samples','Number of samples (X):',min=2,max=10,value=10),
          actionButton("add", "Add scenario")
        )
      })
      
      numScenarios <- reactiveValues(numS=1)
      
      observeEvent(input$add, {showModal(modalDialog(footer = modalButton("Close")))
        numScenarios$numS <- (numScenarios$numS+1)
      })
      
      output$plot <- renderPlot({
        v <- tibble()
        for (i in 1: numScenarios$numS){
          results=tibble(Scenario=i,X=1:input$samples,Y=runif(input$samples))
          v <- bind_rows(v, results)
        }
        v %>% ggplot() + geom_line(aes(x=X, y=Y, colour=as.factor(Scenario)))
      })
    }
    
    shinyApp(ui, server)

MWE code this was adapted from without renderUI:

ui <- fluidPage(
  sliderInput('samples','Number of samples (X):',min=2,max=10,value=10),
  actionButton("add", "Add scenario"),
  plotOutput("plot"),
)

server <- function(input, output, session) {
  
  numScenarios <- reactiveValues(numS=1)
  
  observeEvent(input$add, {showModal(modalDialog(footer = modalButton("Close")))
    numScenarios$numS <- (numScenarios$numS+1)
  })
  
  output$plot <- renderPlot({
    v <- tibble()
    for (i in 1: numScenarios$numS){
      results=tibble(Scenario=i,X=1:input$samples,Y=runif(input$samples))
      v <- bind_rows(v, results)
    }
    v %>% ggplot() + geom_line(aes(x=X, y=Y, colour=as.factor(Scenario)))
  })
}

shinyApp(ui, server)

1 Answers1

3

It's a "scheduling issue". With renderUI(), input$samples doesn't exist when your renderPlot() is called. Exactly why is probably too complicated to work out. But we don't need to - the fix is easy: add

req(input$samples)

at the start of your renderPlot().

By the way,

v <- lapply(
        1:numScenarios$numS,
        function(i) tibble(Scenario=i,X=1:input$samples,Y=runif(input$samples))
     ) %>%
     bind_rows()

is more efficient than your current implementation because you bind the data frames just once at the end of the loop rather than once on each iteration. That's not an issue for a toy example like this, but might be important in real world use.

Limey
  • 10,234
  • 2
  • 12
  • 32
  • I should have been able to solve this one on my own as the use of req() has solved so many of my issues with renderUI. I have assiduously avoided "for-loops" to better tap the power of R, thanks for the lapply. Now let me take a look, make sure I understand everything here... – Curious Jorge - user9788072 Oct 12 '21 at 08:59