user3119875
user3119875

Reputation: 161

Display files on R Shiny using next tab

I have a set of images that I would like to view using R shiny via the next action button. How do I view them one after another using the next button. Every time I run my code, I am able to view the first image however, when I click the next button I get the following error: Warning: Error in $: object of type 'closure' is not subsettable. Here's is the code I have so far.

library(shiny)
library(shinydashboard)

dir_path <- '*/*'
L <- list.files(dir_path, pattern = ".png")

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    # Boxes need to be put in a row (or column)
    fluidRow(
      box(
        title = "Controls", solidHeader = TRUE, status="primary",collapsible = TRUE,
        actionButton("next_image","next")
      ),
      box(
        imageOutput("myimage",width=300,height=300)
      )
    )

  )
)

server <- function(input, output) {

  values<-reactiveValues(data = NULL)
  values$count <- 1


  ntext <- eventReactive(input$next_image,{

    # Check if the counter `values$count` are not equal to the length of your questions
    # if not then increment by 1 and return that image
    # Note that initially the button hasn't been pressed yet so the `ntext()` will not be executed
    if(values$count != length(L)){
      values$count <- values$count + 1
      return(L[values$count])
    }
    else{
      # otherwise just return the last image
      return(L[1])
    }
  })

  ntext <- eventReactive(input$next_image,{

    # Check if the counter `values$count` are not equal to the length of your questions
    # if not then increment  by 1 and return that image
    # Note that initially the button hasn't been pressed yet so the `ntext()` will not be executed
    if(values$count != length(L)){
      values$count <- values$count + 1
      print(values$count)
      return(renderImage({
          path<-file.path(paste( '*/*',L[values$count], sep = ""))

          return(list(src = path, 
                      contentType = "image/png"))
      },
      deleteFile = FALSE
      ))
    }
    else{
      # otherwise just return the last image
      return(L[length(L)])
    }
  })
  output$myimage<- renderImage({
    if (input$next_image == 0){
    path<-file.path(paste( dir_path,L[1], sep = ""))

    return(list(src = path, 
                contentType = "image/png"))} 

    ntext()
  },
  deleteFile = FALSE
  )

}

shinyApp(ui, server)

Upvotes: 0

Views: 80

Answers (1)

Tonio Liebrand
Tonio Liebrand

Reputation: 17689

First of all i suggest creating three sample pictures to make the code fully reproducible: (They will be saved in the working directory)

# Create 3 sample pictures
for(nr in 1:3){
  png(filename = paste0(nr, ".png"))
  plot(nr)
  dev.off()
}

Your server function seems a bit complicated. Actually all you need is:

server <- function(input, output) {

  values <- reactiveValues(count = 1)

  observeEvent(input$next_image,{
      values$count <- min(values$count + 1, length(L))
  })

  output$plot3 <- renderImage({
    list(src = normalizePath(paste0(values$count, ".png")))
  }, deleteFile = FALSE)

}

(Note that I assume here you do not have other .png saved in your working directory.)

For a working app see below:

# Create 3 sample pictures
for(nr in 1:3){
  png(filename = paste0(nr, ".png"))
  plot(nr)
  dev.off()
}
L <- list.files(getwd(), pattern = ".png")

library(shiny)
library(shinydashboard)
ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    # Boxes need to be put in a row (or column)
    fluidRow(
      box(
        title = "Controls", solidHeader = TRUE, status="primary",collapsible = TRUE,
        actionButton("next_image","next")
      ),
      box(
        imageOutput("plot3",width=300,height=300)
      )
    )

  )
)

server <- function(input, output) {

  values <- reactiveValues(count = 1)

  observeEvent(input$next_image,{
      values$count <- min(values$count + 1, length(L))
  })

  output$plot3 <- renderImage({
    list(src = normalizePath(paste0(values$count, ".png")))
  }, deleteFile = FALSE)
}

shinyApp(ui, server)

Upvotes: 1

Related Questions