iceberg
iceberg

Reputation: 65

Saving R Shiny app as a function with arguments passed to the shiny app

I am building an R package that has a function to launch a shiny app. I would like that function to include an argument to be passed to the app. The only way I found to work is setting a global value, and then having the app use that global value:

launch_app <- function(MonteCarlo=1000){
  MonteCarlo_global <<- MonteCarlo
  shiny::runApp(appDir = system.file("app.R", package="my_package"))
}

Is there a better way to pass my "MonteCarlo" argument to be used throughout the shiny app? Please note I'm trying to avoid simply including "MonteCarlo" as one of the input options within the app itself. I'd rather have the user not worry about it. But, if desired the knowledgeable user can control it when launching the app.

Upvotes: 5

Views: 1860

Answers (1)

Gregor de Cillia
Gregor de Cillia

Reputation: 7695

I currently use shinyOptions and getShinyOption to pass arguments to shiny apps.

Also, I source the output from shinyApp directly rather than unsing runApp like so

## file: R/launch_app.R
launch_app <- function(MonteCarlo = 1000){
  shinyOptions(MonteCarlo = MonteCarlo)
  source(system.file("app.R", package = "my_pkg", local = TRUE, chdir = TRUE))$value    
}

The file app.R can look similar to this

## file: inst/app.R
appDir <- getwd()
monte.carlo.default <- 1000
MonteCarlo <- getShinyOption("MonteCarlo", monte.carlo.default)

shinyApp(
  ui = fluidPage(paste("Chosen parameter:", MonteCarlo)),
  server = function(input, output, session){
     oldwd <- setwd(appDir)
     on.exit(setwd(oldwd))
     ## put more server logic here
  }
)

The setwd() part is only relevant if you are using local paths inside your server.

Here you can also find the opinion of the creator of shiny, Joe Cheng, about this topic.

Edit: Why use source instead of runApp?

You are right, the "standard" way is to use runApp, but there are two reasons I chose not to do that:

First, runApp will save all server variables in the global environment. This means that after the app has been stopped, the users of your package will have variables in their workspace that they don't need. If you use the the design I outlined, your user's environments will not be affected by running the app.

Second, by writing your launch_app function like this you can easily deploy apps via shiny-server like so

## file: /srv/shiny-server/my-pkg/app.R
my_pkg::lauch_app(MonteCarlo = 800)

whch is not possible if launch_app invokes runApp. With the runApp approach you need to use a symbolic link to the app folder instead which will lead to more maintenance work (for example, if .libPaths or the structure of inst/ changes). Also, you won't be able to pass parameters to the shiny-server version of your app as easily

Upvotes: 8

Related Questions