rshinyuser-inputshinydashboardgooglesheets4

R Shiny Dashboard: Upload data from both local file and the online database (such as Google Sheet)


I am a beginner of Shiny dashboard and I have a problem that bothered me a long time.
My final target is to assign data to a variable called "myData", but I give the users options to upload data either from local file or online file (in my case GoogleSheet).
Below is a simplified version of my app. To achieve the target, I did:

  1. Under the "data" tab, I create a selection box "input_option", so that the users can choose either uploading local data (="local") or data from a online persistent database (="online);
  2. I use "eventReactive" to source the data conditional on the value of "input_option";
  3. If the user chooses to upload the data from an online database, the data will be displayed in the dashboard body;
  4. If the user chooses to upload data from a local file, in the dashboard body, it will show the "fileInput" box to guide the user choose the local file. Then the data will also be displayed underneath in the dashboard body.

However, the problems are:

  1. In either way, the data cannot be displayed in the dashboard body. I don't even know if the data has been successfully sourced;
  2. When I choose to upload online data and then close the app, the R console does not pause but keeping running.

Could any friends or experts help me with the problems? I really really appreciate your help!

library(shiny)
library(shinydashboard)
library(googlesheets4)
library(googledrive)

server = function(session, input, output)
{
  # "input_option" is used to select whether input data from local or online
  input_option = reactive(
    input$select_upload
  )
  
  # Upload the data
  myData = eventReactive(
    input$select_upload,
    if(input$select_upload == "local")
    {
      req(input$file_myData)
      read.csv(
        input$file_myData$datapath, 
        header = T, 
        stringsAsFactors = F, 
        sep = input$sep_file_myData)
    }
    else if(input_option() == "online")
    {
      as.data.frame(gs4_find("myData_sample") %>% range_read())
    }
  )
  
  # display the myData data uplaoded ---
  output$display_myData = eventReactive(
    myData(),
    DT::renderDataTable(
      myData(), options = list(scrollX = T)
    )
  )
}

ui = dashboardPage(
  dashboardHeader(title = "My dashboard"),
  dashboardSidebar(
    sidebarMenu(
      id = "sidebarmenu",
      menuItem("Data upload", tabName = "data", icon = icon("database")),
      conditionalPanel(
        "input.sidebarmenu === 'data'",
        selectInput(
          inputId = "select_upload", 
          label = "please select an option", 
          choices = c("local", "online"),
          selected = "local"
        )
      )
    )
  ),
  
  dashboardBody(
    tabItems(
      tabItem(
        tabName = "data",
        conditionalPanel(
          condition = "input.select_upload === 'local'",
          fileInput(inputId = "file_myData", 
                    label = "Choose csv file", 
                    accept = c("text/csv", "text/comma-separated-values", "text/plain", ".csv")),
          radioButtons(inputId = "sep_file_myData", "Separator", 
                       choices = c(Comma = ",", Semicolon = ";", Tab = "\t"), 
                       selected = ",")
        ),
        fluidRow(
          box(
            title = "myData information uploaded", solidHeader = T, status = "primary",
            width = 12,
            DT::dataTableOutput(outputId = "display_myData")
          )
        )
      )
    )
  )
)

shinyApp(ui, server)

Solution

  • Two changes in the server will make the local file work, and probably the googledrive one too.

    server = function(session, input, output)
    {
      # "input_option" is used to select whether input data from local or online
      input_option = reactive(
        input$select_upload
      )
      
      # Upload the data
      myData = eventReactive(
        input$file_myData, # HERE!
        if(input$select_upload == "local")
        {
          req(input$file_myData)
          read.csv(
            input$file_myData$datapath, 
            header = T, 
            stringsAsFactors = F, 
            sep = input$sep_file_myData)
        }
        else if(input_option() == "online")
        {
          as.data.frame(gs4_find("myData_sample") %>% range_read())
        }
      )
      
      # display the myData data uplaoded --- # AND HERE!
      output$display_myData = DT::renderDataTable(
        myData(), 
        options = list(scrollX = T)
      )
    }
    

    For you two questions at the end of your post:

    1. You can debug shiny apps with the old school method of sticking print() statements in your code. Watch the R console to see where in your code is/isn't being reached when you perform actions in your app. You can also use str() to print to the screen the structure of objects which only exist when the app is running so you can work out how to deal with them.
    2. This is normal behaviour - your app is running even with the browser tab closed. Note you can close the tab and reopen a new one (if you copied the link from the address bar). Also you can open multiple tabs at the same time! To close the app, just hit escape a couple of times in RStudio.