Search code examples
rshinyflexdashboard

How to override (upon actionButton click) a reactive object in R Shiny Flexdashboard


Am trying to make an R Shiny Flexdashboard that allows the user to utilise either a local Excel file or a downloaded Googlesheet, as a data source.

I have created an example here but I have used a local csv file to stand in place for the Googlesheets download component (using googlesheets in the example would be complicated).

https://gist.github.com/jtag04/67ae6b2c39e4f68f90e06bb1ce2ceb98

The script above works (save this as an *.rmd file for it to run -it's a Flexdashboard).

However, my challenge is that I want the *csv upload (when the actionButton is pressed) to override the Excel file object (if it exists).

i.e instead of saving the csv to step_one_2 (as in the example), for it to override the step_one object (if it exists).

Is this possible? Many thanks in advance.


Solution

  • One way to achieve something like this (if I understand everything correctly) would be to use radioButtons to let the user choose the input type. Then render a different input element dependent on user choice, and have a reactive that deals with the two different input file types appropriately. At the end, we are rendering a single table, either from excel or googlesheets file.

    Code:

    library(shiny)
    library(tidyverse)
    
    # let the user choose the type of input file
    radioButtons(
      inputId = "what_source",
      label = "Choose source file",
      choices = c("googlesheets", "excel"),
      inline = FALSE
      )
    
    # render file input widgets conditioned on user choice
    conditionalPanel(condition = 'input.what_source == "googlesheets"',
                     fileInput("google_file", "Upload from csv", accept = ".csv")
                     )
    
    conditionalPanel(condition = 'input.what_source == "excel"',
                     fileInput("excel_file", "Upload from excel", accept = ".xlsx")
                     )
    
    # deal with the file selected by the user
    what_file <- reactive({
      if (input$what_source == "googlesheets") {
        x <- readr::read_csv(input$google_file$datapath) %>% mutate(source = "csv")
      } else {
        x <- readxl::read_excel(input$excel_file$datapath) %>% mutate(source = "Excel")
      return(x)
      }
    })
    
    # then in a different element downstream add the render function:
    renderDataTable(what_file())
    

    Update: Fetch csv at will, but change to excel input with checkbox:

    Server logic:

    # fetch updated csv data
    actionButton("fetch", "Fetch new data")
    checkboxInput("excel", label = "Get excel file", value = FALSE)
    
    fetch_new <- eventReactive(input$fetch, {
      readr::read_csv("df.csv")
    })
    
    conditionalPanel(condition = 'input.excel == true',
                     fileInput("excel_file", 
                               "Upload from excel", 
                                accept = ".xlsx")
                     )
    
    what_file <- reactive({
      if (!input$excel) {
        x <- fetch_new()
      } else {
        x <- readxl::read_excel(input$excel_file$datapath)
      return(x)
      }
    })