jff
jff

Reputation: 320

Dynamically add plot with title in shiny

I want to dinamically generate plots using shiny, but each plot with a different title.

I have tried using the for bucle to generate n number of plots and show them using an observeEvent, but this is not working for me, as the main of the plot is ignored.

To ensure that each plot has its own main title, what I do is to store the title into a data.frame and access to it from the plot.

Here the code:

    library(shiny)

ui <- fluidPage(

    textInput("title","Title",""),
    actionButton("generate","Plot"),
    div(class="aux",style="width:300px;height:200px")

)


server <- function(input,output){

    observeEvent(input$generate,{
                  insertUI(
                      selector= ".aux",
                      where="beforeBegin",
                      ui = plotOutput(paste0("plot",input$generate))

                  )

        if(input$generate == 1){

            data <<- data.frame(title = input$title)
        }else{
            aux <- data.frame(title=input$title)
            data <<- rbind(data,aux)

        }   


    })

    for(i in 1:10){

        output[[paste0("plot",i)]] <- renderPlot(
            plot(rnorm(100),main=data[i,"title"])

        )


    }



}


shinyApp(ui,server)

This other code do what I really want to do, but it is not good programing to declare manually the plots:

library(shiny)

ui <- fluidPage(

    textInput("title","Title",""),
    actionButton("generate","Plot"),
    div(class="aux",style="width:300px;height:200px")

)


server <- function(input,output){

    observeEvent(input$generate,{
                  insertUI(
                      selector= ".aux",
                      where="beforeBegin",
                      ui = plotOutput(paste0("plot",input$generate))

                  )

        if(input$generate == 1){

            data <<- data.frame(title = input$title)
        }else{
            aux <- data.frame(title=input$title)
            data <<- rbind(data,aux)

        }   


    })



        output$plot1 <- renderPlot(
            plot(rnorm(100),main=data[1,"title"])
        )
        output$plot2 <-    output$plot1 <- renderPlot(
            plot(rnorm(100),main=data[2,"title"])
        )





}


shinyApp(ui,server)

EDITED:

Using the recomendations of Stephane Laurent, I have put the insertUI and output[[plot]] inside the observeEvent, but this not solves the issue to be able to edit the plot title changing the data.frame title. Here the code:

library(shiny)
library(data.table)

ui <- fluidPage(
  column(6,
  textInput("title","Title",""),
  actionButton("generate","Plot"),
  div(id="aux")),
  column(6,
  textInput("newt","New title",""),
  selectInput("row","Row",choices=c(1:10)),
  actionButton("change","Change title"))


)


server <- function(input,output){
  observeEvent(input$change,{
    df$title <<- as.character(df$title)
    df[input$row,"title"]<-input$newt 


  })
  k <- 0
  observeEvent(input$generate, {
    insertUI(
      selector= "#aux",
      where="beforeBegin",
      ui = plotOutput(paste0("plot",input$generate))
    )
    k <- k + input$generate
    if(input$generate==1){
      df <<- data.frame(title = input$title)
      df$title <<- as.character(df$title)

    }else{

      aux <- data.frame(title = input$title)
      df <<- rbind(df,aux)
      df$title <<- as.character(df$title)
    }


    output[[paste0("plot",input$generate)]] <- renderPlot(
      plot(rnorm(100), main = df[k,"title"])      
    )









  })  
}

shinyApp(ui,server)

Upvotes: 1

Views: 2505

Answers (1)

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84519

Put the renderPlot inside the observer:

library(shiny)

ui <- fluidPage(

  textInput("title","Title",""),
  actionButton("generate","Plot"),
  div(id="aux")

)


server <- function(input,output){

  observeEvent(input$generate, {
    insertUI(
      selector= "#aux",
      where="beforeBegin",
      ui = plotOutput(paste0("plot",input$generate))
    )

    output[[paste0("plot",input$generate)]] <- renderPlot(
      plot(rnorm(100), main = isolate(input$title))      
    )
  })  
}

shinyApp(ui,server)

EDIT

Solution for the edited question:

library(shiny)

ui <- fluidPage(

  column(6,
         textInput("title","Title",""),
         actionButton("generate","Plot"),
         div(id="aux")),
  column(6,
         textInput("newt","New title",""),
         selectInput("row","Row",choices=c(1:10)),
         actionButton("change","Change title"))  
)    

server <- function(input,output){

  titles <- reactiveValues()

  observeEvent(input$change, {
    titles[[input$row]] <- input$newt
  })

  values <- replicate(10, rnorm(100))

  for(i in 1:10){
    local({
      ii <- i
      output[[paste0("plot",ii)]] <- renderPlot(
        plot(values[,ii], main = titles[[as.character(ii)]])
      )
    })
  }

  observeEvent(input$generate, {
    titles[[as.character(input$generate)]] <- input$title
    insertUI(
      selector = "#aux",
      where = "beforeBegin",
      ui = plotOutput(paste0("plot",input$generate))
    )
  })

}

shinyApp(ui,server)

Upvotes: 2

Related Questions