Search code examples
rshinyshinydashboard

Is there a way to make my shiny app accept passing of arguments from users?


I have got R shiny app that I coded in R studio with separate ui.R, server.R, global.R, and a www folder with some pictures in it. What the app does is that it displays the images from a directory specified in its global.R file. The images have checkboxes allowing user to select images. Once users select their pictures and press the action button called "Create", the app creates 2 text files listing the filenames of the images selected and not selected by user in the app directory.

Now, what I would really need help with are 2 things:

  1. Instead of specifying the images directory and the project name in the global.R file, I would like to make my app accept arguments from users, i.e., I would like the users to, somehow when running the app, specify the images directory and the project name (name to be used later in creating the text files). Ideally, I would like to make my global.R file blank, with no code in it. Is that possible? One friend of my mine is suggesting I can use something called ShinyOptions and getShinyOtion but neither me nor he are familiar with that.

  2. If I am to run the app from the command line (terminal) of my computer (not the terminal in Rstudio), what do I need to do?

So, if anyone has an idea using those or others would really appreciate their help.

To help reproduce my case, below I am including the code I currently have in my ui.R, server.R, and global.R.

ui

library(shiny)
library(shinydashboard)

dashboardPage(
  dashboardHeader(title = "Pictures List"),
  dashboardSidebar(
    actionButton("the_action_button", "Create", width = "100%")
  ),
  dashboardBody(
    fluidRow(
      box(
        title = "Picture Selection",
        width = 12,
        uiOutput("image_selection")
      )
    )
  )
)

server

library(shiny)
library(shinydashboard)

function(input, output, session) {
  
  # Get a list of available image files from the specified folder
  
  image_files <- list.files(image_folder, pattern = "\\.png$", full.names = FALSE)
  
  # Initialize a list to store selected images
  selected_images <- reactiveVal(character(0))
  
  # Render UI for image selection
  output$image_selection <- renderUI({
    tagList(
      lapply(image_files, function(img) {
        img_tag <- tags$img(src = img, width = "100%")
        checkbox_tag <- checkboxInput(
          inputId = img,
          label = NULL,
          value = img %in% selected_images()
        )
        div(img_tag, checkbox_tag)
      })
    )
  })
  
  # Create and download text files based on selected images
  observeEvent(input$the_action_button, {
    # Create a timestamp for the filenames
    timestamp <- format(Sys.time(), format = "%Y%m%d")
    
    # Create text file for images not selected
    not_selected_images <- setdiff(image_files, selected_images())
    not_selected_filename <- paste0("not_selected_file_", project_name,
                                    "_", timestamp, ".txt")
    writeLines(not_selected_images, con = not_selected_filename)
    
    # Create text file for selected images
    selected_images <- selected_images()
    selected_filename <- paste0("selected_file_list_", project_name, 
                                "_", timestamp, ".txt")
    writeLines(selected_images, con = selected_filename)
  })
}

global

image_folder <- "~/Desktop/pictures_folder"
project_name <- "land_project"

Solution

  • Although I think that shinyOptions solution is more elegant, if we don't want to use getShinyOption I propose doing the following:

    • Pass the paths as an argument and assign them to the global environment so the app can reach them.
    • Remove variables assigned after the function finished executing with on.exit
    my_app <- function(image_folder = "~/Desktop/pictures_folder",
                       project_name = "land_project") {
        image_folder <<- image_folder
        project_name <<- project_name
        on.exit({
            rm(list = c("image_folder", "project_name"), envir = .GlobalEnv)
            message("clearing image_folder variable")
        })
        shiny::runApp()
    }
    
    my_app()