skip to Main Content

According to the help in renderPlot, renderPlot should be executing within the parent environment calling it. Nevertheless, in the minimal example hereafter I can’t get to plot three different graphics :

library("shiny")
plotNames <- c("plot1", "plot2","plot3")
ui <- basicPage(uiOutput("all"))
server <- function(input, output,session) {
   prepGraph <- reactiveVal(NULL)
   output$all <- renderUI({
      items <- list()
      for(iCode in 1:length(plotNames)){
          items[[iCode]] <- plotOutput(plotNames[iCode])
      }
      for(code in plotNames){
        cat("ntestParent:",code)
        output[[code]] <- renderPlot({
            cat("ntestRender:",code)
            plot(1,main=code)
        })
      }

      prepGraph(TRUE)
      return(do.call(tagList,items))
  })
}
test <- shinyApp(ui, server)

Returns three identitical plots titled "plot3" and on the command line:

Listening on http://127.0.0.1:3842

testParent: plot1

testParent: plot2

testParent: plot3

testRender: plot3

testRender: plot3

testRender: plot3

How can I do a loop for renderPlot on the different codes ?

Environment: R 3.6.3 on Ubuntu 20.04.6

2

Answers


  1. Chosen as BEST ANSWER

    Just specifying the environment in renderPlot call fixes it.

    Defining an environment:

     locEnv <- rlang::env(code=code)  
    

    Final minimal example with call to this environment in renderPlot :

    library("shiny")
    plotNames <- c("plot1", "plot2","plot3")
    ui <- basicPage(uiOutput("all"))
    server <- function(input, output,session) {
        prepGraph <- reactiveVal(NULL)
        output$all <- renderUI({
            items <- list()
            for(iCode in 1:length(plotNames)){
                items[[iCode]] <- plotOutput(plotNames[iCode])
            }
            for(code in plotNames){
                cat("ntestParent:",code)
                locEnv <- rlang::env(code=code)
                output[[code]] <- renderPlot({
                    cat("ntestRender:",code)
                    plot(1,main=code)
                },env=locEnv)
            }
            prepGraph(TRUE)
            return(do.call(tagList,items))
        })
    }
    test <- shinyApp(ui, server)
    

    This doesn't explain why the normal call doesn't work though ...


  2. That is due to lazy evaluation. Replace for loop with lapply and it will work. Try this

    library("shiny")
    plotNames <- c("plot1", "plot2","plot3")
    ui <- basicPage(uiOutput("all"))
    server <- function(input, output,session) {
      prepGraph <- reactiveVal(NULL)
      
      output$all <- renderUI({
        items <- list()
        lapply(1:(length(plotNames)), function(iCode){
        # for(iCode in 1:length(plotNames)){
          items[[iCode]] <<- plotOutput(plotNames[iCode])
        })
        lapply(plotNames, function(code){
        # for(code in plotNames){
          cat("ntestParent:",code)
          output[[code]] <- renderPlot({
            cat("ntestRender:",code)
            plot(1,main=code)
          })
        })
        
        prepGraph(TRUE)
        return(do.call(tagList,items))
      })
    }
    test <- shinyApp(ui, server)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search