1

Here is a sample code to generate a plot upon clicking the actionButton.

shinyApp(
shinyUI(fluidPage(
    inputPanel( 
        numericInput("n", "n", 10),
        actionButton("update", "Update")
    ),
    plotOutput("plot")
)),

shinyServer(function(input, output) {
    values <- reactiveValues()
    values$data <- c()

    obs <- observe({
        input$update
        isolate({ values$data <- c(values$data, runif(as.numeric(input$n), -10, 10)) })
    }, suspended=TRUE)

    obs2 <- observe({
        if (input$update > 0) obs$resume()
    })

    output$plot <- renderPlot({
        dat <- values$data
        hist(dat)
    })
}) 

)

I would like to display a default plot which is in www/test.png to appear when the application is launched. And then change the plot after clicking the actionButton as per the user input.

chas
  • 1,565
  • 5
  • 26
  • 54
  • is it necessary to show a png or would be a default R-plot sufficient as well? Both is possible yet the later is easier – mnist Mar 22 '20 at 09:54
  • It needs to be a png or whatever image format but which is already generated and stored in www/ directory. – chas Mar 22 '20 at 10:58

3 Answers3

1

First, I create a simple plot, export it as an image (manually, not in code) and name it Rplot.png (save it where you want):

plot(mtcars$mpg)

Then, in the shiny app, we have to distinguish two situations :

  • when the app starts, no button is clicked yet, we render the image with renderImage

  • when we click on the button, we replace renderImage with renderPlot and render an interactive plot

This means that we must use uiOutput in ui part so that we can choose the output to be an image or a plot according to the situation.

Here's an example (I didn't adapt your code but it should not be too difficult):

library(shiny)

# determine your path to image here (you should use the package "here" to do so)

ui <- fluidPage(
  selectInput("choice", "Choose", choices = names(mtcars)),
  actionButton("run", "Run"),
  uiOutput("some_ui")
)

server <- function(input, output, session) {

  ### "Static" part: no click on actionButton yet
  output$some_ui <- renderUI({
    imageOutput("image_plot")
  })

  output$image_plot <- renderImage({
    list(src = "Rplot.png",
         contentType = 'image/png')
  }, deleteFile = FALSE) # Do not forget this option



  ### Click on actionButton
  observeEvent(input$run, {
    output$some_ui <- renderUI({
      plotOutput("dynamic_plot")
    })

    output$dynamic_plot <- renderPlot({
      plot(mtcars[[input$choice]])
    })
  })

}

shinyApp(ui, server)
bretauv
  • 7,756
  • 2
  • 20
  • 57
1

The key is to use renderUI, so you can either show an image or a R plot. This should do what you desire:

shinyApp(
  shinyUI(fluidPage(
    inputPanel( 
      numericInput("n", "n", 10),
      actionButton("update", "Update")
    ),
    uiOutput("out")
  )),

  shinyServer(function(session, input, output) {
    values <- reactiveValues()

    # check if plot has been already rendered
    check <- reactiveVal(FALSE)
    values$data <- c()

    observeEvent(input$update, {
      # set check to TRUE
      check(TRUE)
      input$update
      values$data <- c(values$data, runif(as.numeric(input$n), -10, 10))
      dat <- values$data
      output$plot <- renderPlot({
        hist(dat)
      })
    })

    # initial picture. 
    output$picture <- renderImage({
      list(src = "temp.png")
    }, deleteFile = FALSE)


    output$out <- renderUI({
      # in the  beginning, check is FALSE and the picture is shown
      if (!check()) {
        imageOutput("picture")
      } else {
        # as soon as the button has been pressed the first time,
        # the plot is shown
        plotOutput("plot")
      }


    })
  }) 

)
mnist
  • 6,571
  • 1
  • 18
  • 41
  • where should the "temp.png" be located in this case? – chas Mar 22 '20 at 18:13
  • in the same folder as your app.R file is. – mnist Mar 22 '20 at 18:14
  • `##render initial picture. heatmap_rna is the id for the uiOutput() in ui.R## output$heatmap_rna <- renderImage({ list(src = "/www/heatmap.png") }, deleteFile = FALSE) ###generate plot upon action button## output$heatmap_rna <- renderPlot({ if(input$action==0) return() print("heatmap_rna_renderPlot") heatmap_render() ##custom function which produces the heatmap })` – chas Mar 22 '20 at 18:36
  • i have adapted the code given by you in the above way to my need. `renderPlot` is generated by a custom function `heatmap_render()`. And instead of `observeEvent` i have used `input$action ==0`. Is there something wrong in this as the above code gives the error `Error in pngfun: invalid quartz() device size` – chas Mar 22 '20 at 18:40
  • no clue of how to help here. In case you cannot fix it, please open another question on SO – mnist Mar 22 '20 at 19:46
  • i have new OP related to this `https://stackoverflow.com/questions/60811581/how-to-render-default-plot-in-r-shiny` if you have time to check. – chas Mar 23 '20 at 10:17
  • how is this different from my answer below? – bretauv Mar 23 '20 at 11:07
  • it is not different but as i have explained both approaches are not working in my case. it may be different with the way the action Button trigger is written. – chas Mar 23 '20 at 11:15
0

I know, that this has been solved a while, but I needed a solution, without uiOutput. Plus I find this much simpler.

library(shiny)

if (interactive()) {
  shinyApp(
    ui = fluidPage(
      actionButton("btn", "Click me"),
      br(),
      plotOutput('some_plot', width = '100%')
    ),
    server = function(input, output) {
      output$some_plot <- renderPlot({
        if (!input$btn) {
          # default plot
          plot(1, 1, col = 'red')
        } else{
          # updated plot
          plot(1000, 1000, col = 'green')
        }
      })
    }
  )
}
Steffen
  • 206
  • 1
  • 7