4
votes

My goal is to retrieve data from a googlesheet and map it on a leaflet map.
Everything is working fine, only if the code to retrieve data from googlesheet is placed in the global.R and it is only valid for that session of the running shiny app.
However, if meanwhile the sheet is updated, these updates are not reflected in the running session. So I need to wire up a ui.R button to fetch new data each time the button is fired and pass the data onto the relevant codes in server.R . (I hope this is clear).

In my current setup, the data gets downloaded from googlesheet (via global.R) and passed on to the environment and used for that running app session.
Here is my working shiny app setup:

ui.R

...
leafletOutput("map"),
actionButton("button", "Get New Data")
...
#added the below lines to update the question:
                        selectInput("Country",
                                    "Country:",
                                    c("All",
                                      unique(as.character(draw$Country))))

server.R

shinyServer(function(input, output, session) {
#... 
  output$map <- renderLeaflet({
#... some options here
})
  draw <- mydata
  drawvalue <- reactive({
    if (input$year == year1){return(mydata)} else {
      filtered <- filter(mydata, Type == input$type1)
      return(filtered)
    } 
  })
  observe({
#... some other variable definitions
    colorBy <- input$color  ##added to update the question
    sizeBy <- input$size   ##added to update the question

    draw <- drawvalue()
    colorData <- draw[[colorBy]]  ##added to update the question

#... code related to the leaflet
  })
#...
}

global.R

mydata <- gs_read(gs_key("0123456abcdabcd123123123"))


After some reading and exploring, I am told that I have to use reactive and observeEvent. But my faulty setup results in error, saying that 'object "mydata" not found'.
I tried in the server.R: (I know the code below is all faulty)

observeEvent(input$button,{
mydata <- gs_read(gs_key("0123456abcdabcd123123123"))
})

mydata <- eventReactive(input$button,{
mydata()
})

update:



in my ui.R, I also refer to "draw", this also bugs. How should I change this one? I updated the lines in the ui.R above in the question. this line is part of the ui.R line which call the DT package to show some tables.

by the way, this app is based on the superzip shiny app.
NB: I will give 100 points bounty for the accepted answer.

1
This seems like a job for a reactivePoll/reactiveFileReader, does the connection to google docs have a lightweight check to see if the data has been modified? - Shape

1 Answers

6
votes

In general observe and observeEvent do not return any value and they are used for side effects. So this part of the code below doesn't return any value and even if you used <<- to override the variable mydata shiny wouldn't know that its value has changed.

observeEvent(input$button,{
mydata <- gs_read(gs_key("0123456abcdabcd123123123"))
})

So if you want shiny to know when the data is updated you should read it within reactive environment. So, instead of reading the data via global.R I would advice to do following within server.R:

mydata <- eventReactive(input$button, {
    gs_read(gs_key("0123456abcdabcd123123123"))
  })

After clicking the button shiny would read (new) data which could be then accessed with mydata() and passed to the render* functions and other reactive parts of the code. For example:

drawvalue <- reactive({
  if (input$year == year1){return(mydata() )} else { # added () 
    filtered <- filter(mydata(), Type == input$type1) # added () to mydata
    return(filtered)
  } 
})

You had to change this part of code

draw <- drawvalue()

to

draw <- reactive({ drawvalue() })

and then access it with draw()


UPDATE:

If you want make choices of the widget selectInput from UI.R dependent on draw you can do following:

1) Add the parameter session to the server function for updateSelectInput

shinyServer(function(input, output, session) {...} # added session 

2) Set choices of the widget in UI.R to ""

selectInput("Country", "Country:", choices = "")

3) Update the choices on the server side with:

observe({
    req(draw()) # require that draw is available
    updateSelectInput(session, "Country", "Country:",
                c("All", unique(as.character(draw()$Country))))  # added ()
  })