4

This is pretty much the same question as presented here: dynamically add plots to web page using shiny

But instead of producing a variable number of plots (which I've successfully done), I am trying to upload a selection of images into the application and display them on the user interface. Using the same approach as described in the question above, I've produced my application with the code below. But only the first image is rendering in the UI.

What obvious thing have I missed today?

R 3.2.2 (Windows 7) shiny 0.12.2

server.R

library(shiny)

shinyServer(function(input, output) {
  output$files <- renderTable(input$files)

  files <- reactive({
    files <- input$files
    files$datapath <- gsub("\\\\", "/", files$datapath)
    files
  })


  output$images <- renderUI({
    image_output_list <- 
      lapply(seq_along(nrow(files())),
             function(i)
             {
               imagename = paste0("image", i)
               imageOutput(imagename)
             })

    do.call(tagList, image_output_list)
  })

  observe({
    for (i in seq_along(nrow(files())))
    {
      local({
        my_i <- i
        imagename = paste0("image", my_i)
        output[[imagename]] <- 
          renderImage({
            list(src = files()$datapath[my_i],
                 alt = "Image failed to render")
          }, deleteFile = FALSE)
      })
    }
  })

})

ui.R

library(shiny)

shinyUI(fluidPage(
  titlePanel("Uploading Files"),
  sidebarLayout(
    sidebarPanel(
      fileInput(inputId = 'files', 
                label = 'Select an Image',
                multiple = TRUE,
                accept=c('image/png', 'image/jpeg'))
    ),
    mainPanel(
      tableOutput('files'),
      uiOutput('images')
    )
  )
))

Image1.PNG Image2.JPG Image3.JPEG

Community
  • 1
  • 1
Benjamin
  • 16,897
  • 6
  • 45
  • 65

1 Answers1

13

Your so close! Try this:

library(shiny)

server <- shinyServer(function(input, output) {
  output$files <- renderTable(input$files)

  files <- reactive({
    files <- input$files
    files$datapath <- gsub("\\\\", "/", files$datapath)
    files
  })


  output$images <- renderUI({
    if(is.null(input$files)) return(NULL)
    image_output_list <- 
      lapply(1:nrow(files()),
             function(i)
             {
               imagename = paste0("image", i)
               imageOutput(imagename)
             })

    do.call(tagList, image_output_list)
  })

  observe({
    if(is.null(input$files)) return(NULL)
    for (i in 1:nrow(files()))
    {
      print(i)
      local({
        my_i <- i
        imagename = paste0("image", my_i)
        print(imagename)
        output[[imagename]] <- 
          renderImage({
            list(src = files()$datapath[my_i],
                 alt = "Image failed to render")
          }, deleteFile = FALSE)
      })
    }
  })

})

ui <- shinyUI(fluidPage(
  titlePanel("Uploading Files"),
  sidebarLayout(
    sidebarPanel(
      fileInput(inputId = 'files', 
                label = 'Select an Image',
                multiple = TRUE,
                accept=c('image/png', 'image/jpeg'))
    ),
    mainPanel(
      tableOutput('files'),
      uiOutput('images')
    )
  )
))

shinyApp(ui=ui,server=server)

I changed seq_along to just 1:nrow(files()) but seq_len(nrow(files())) or seq_along(t(files())) would work to.

RmIu
  • 4,357
  • 1
  • 21
  • 24