18.3 Server Functions

  • Long reactives should be put into a non-reactive functions outside the server
    • easier to debug
    • easier to tell what inputs were passed to a function vs a reactive expression

CASE 1: Reading uploaded data

server <- function(input, output, session) {
  data <- reactive({
    req(input$file)
    
    ext <- tools::file_ext(input$file$name)
    switch(ext,
      csv = vroom::vroom(input$file$datapath, delim = ","),
      tsv = vroom::vroom(input$file$datapath, delim = "\t"),
      validate("Invalid file; Please upload a .csv or .tsv file")
    )
  })
  
  output$head <- renderTable({
    head(data(), input$n)
  })
}

To a function that extracts:

# IN ITS OWN FILE
load_file <- function(name, path) {
  ext <- tools::file_ext(name)
  switch(ext,
    csv = vroom::vroom(path, delim = ","),
    tsv = vroom::vroom(path, delim = "\t"),
    # validate works similarly to stop() outside of shiny
    validate("Invalid file; Please upload a .csv or .tsv file")
  )
}
#----------------------------------------------
server <- function(input, output, session) {
  data <- reactive({
    req(input$file)
    load_file(input$file$name, input$file$datapath)
  })
  
  output$head <- renderTable({
    head(data(), input$n)
  })
}

Note: generally better to keep reactive and non-reactive parts of app as separate as possible

18.3.1 Internal functions

If the function needs to use input, output or session, it makes more sense to write the function directly in the server

server <- function(input, output, session) {
  switch_page <- function(i) {
    updateTabsetPanel(input = "wizard", selected = paste0("page_", i))
  }
  
  observeEvent(input$page_12, switch_page(2))
  observeEvent(input$page_21, switch_page(1))
  observeEvent(input$page_23, switch_page(3))
  observeEvent(input$page_32, switch_page(2))
}