Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically display images from upload in Shiny UI

Tags:

r

shiny

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

like image 837
Benjamin Avatar asked Dec 14 '22 10:12

Benjamin


1 Answers

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.

like image 123
RmIu Avatar answered Jan 05 '23 20:01

RmIu