jackolney / baldr

Epidemiological modelling in R
https://jackolney.github.io/baldr/
MIT License
3 stars 0 forks source link

Move shiny app from inst into R #21

Open richfitz opened 6 years ago

richfitz commented 6 years ago

This will make it easier to write tests for components

richfitz commented 6 years ago

At the same time, most of the code in R/ is not that obviously useful. I'd suggest moving the shiny app code into the main package, and moving the odin code listings into inst

jackolney commented 6 years ago

https://github.com/wlandau/appPackage

jackolney commented 6 years ago

@richfitz beginning to think this is not entirely doable at the moment. I did try something similar before, but forgot why it didn't work.

All user defined functions can be moved to /R – no problem.

But, because the UI is complex, I break it up into smaller chunks that I then source("file")$value in to the main ui.R

For the server files, theres a whole list of objects that are called in the app.R file and exist within the shinyServer() these are things like output$plot <- renderPlot() and so if they went into /R I'd obviously get a whole host of error messages.

The idea in appPackage works for a simple app because the entire app can be contained in a ui and a server function in a couple of lines. Not sure how I can make this work for a much larger app.

Stepped away from putting all the functions that the app relies on in /R as I ended up doing all this ../../R/someFunction kind of stuff. Will keep digging and thinking on this though.

jackolney commented 6 years ago

@richfitz figured it out, for UI at least 😄

# Standard server function
my_server <- function(input, output) {
  output$distPlot <- renderPlot({
    my_plot(input$obs)
  })
}

my_ui <- function(){fluidPage(
  sidebarLayout(
    sidebarPanel(
      sliderInput("obs", "Number of observations:", min = 10, max = 500, value = 100),
      slideFunc()
    ),
    mainPanel(plotOutput("distPlot"))
  )
)}

my_plot = function(number_observations){
  hist(rnorm(number_observations), col = 'darkgray', border = 'white')
}

my_app = function(){
  shinyApp(ui = my_ui(), server = my_server)
}

# Testing to see if you can return a UI object from a function to the main UI function
slideFunc <- function() {
    obj <- sliderInput("dirs","Number of something:", min = 10, max = 500, value = 100)
    return(obj)
}

# You can.
# However, for server functions... is more complex, as they rely on I/O stuff.

I think that this might be the answer though. Creating a "module" for each big chunk of code: https://shiny.rstudio.com/articles/modules.html

richfitz commented 6 years ago

Odd that it's so complicated to do - would have thought that this would be a fairly common use-case