thebigmcrae
thebigmcrae

Reputation: 81

Using observe event variables in later code

I am trying to create an app that allows a user to click on a map, press go, and receive a table of values for that point. I have 2 netCDF files that are stored on Dropbox that I access and save as rasterStacks to get the output data.

In my server function I have an observe event for the map click, however when I go to use the value for latitude or longitude later in the server function I get the error "could not find function "clng", with clng being what I saved the click$longitude to.

Any help would be greatly appreciated.

Thanks, Kirby

library(shiny)
library(leaflet)
library(raster)
library(tidyverse)
library(DT)
library(mailR)

# Read NetCDF Files from public share links 
if(!exists("ettemp")){
  ettemp <- tempfile("et", fileext = ".nc")
}

if(!exists("preciptemp")){
  preciptemp <- tempfile("precip", fileext = ".nc")
}

if(!file.exists(ettemp)){

  download.file(url = "https://www.dropbox.com/s/uyq9arqgnprxzv1/ET.nc?raw=1",
                destfile = ettemp,
                mode = "wb")
}

if(!file.exists(preciptemp)){

  download.file(url = "https://www.dropbox.com/s/sgmhq8cmth1jd8h/precip.nc?raw=1",
                destfile = preciptemp,
                mode = "wb")
}

precip_lowres <- stack(preciptemp)
names(precip_lowres) <- month.name


ET_stack <- stack(ettemp)
names(ET_stack) <- month.name


ui <- fluidPage(
  leafletOutput("map"),
  actionButton("go", "Go"),
  DT::dataTableOutput(outputId = "mytable")
)

server <- shinyServer(function(input, output, session) {

  output$map <- renderLeaflet({

    leaflet() %>%
    setView(lat = 35, lng = -100, zoom = 3) %>%
    addTiles(options = providerTileOptions(noWrap = TRUE)) 
  })

  observeEvent(input$map_click, {
    click <- input$map_click
    clat <- click$lat
    clng <- click$lng

    leafletProxy('map') %>%
      clearMarkers() %>% 
      addMarkers(lng=clng, lat=clat,
                 popup = paste(round(click$lat, 2), round(click$lng, 2)))

  })


  coordvals <- eventReactive(input$go, {

    coords <- data.frame(cbind(clng(), clat()))

    coordinates(coords) <- ~ X1 + X2

    precip_vals <- data.frame(raster::extract(precip_lowres, coords)) %>%
      gather(key = "Month", value = "Precip") %>%
      mutate(Precip = round(Precip, 0))

    ET_vals <- data.frame(raster::extract(ET_stack, coords)) %>%
      gather(key = "Month", value = "ET")

    combo_vals <- precip_vals %>%
      left_join(ET_vals) %>%
      mutate(ET = ET*3)

    combo_vals$Month <- factor(combo_vals$Month, levels = month.name)
  })

  output$mytable <- DT::renderDataTable({
    datatable(coordvals())
  })

})

shinyApp(ui, server)

Upvotes: 0

Views: 3001

Answers (1)

Alex P
Alex P

Reputation: 1494

Below I used reactiveValues() to initialize click, clat, and clng. Might be cleaner to define them as separate reactive() expressions. Either way, if you want to use them outside of the observeEvent(handlerExpr={}) argument, you should probably define them outside of the observeEvent(). Use the handlerExpr to update their values.

library(shiny)
library(leaflet)
library(raster)
library(tidyverse)
library(DT)
library(mailR)

# Read NetCDF Files from public share links 
if(!exists("ettemp")){
  ettemp <- tempfile("et", fileext = ".nc")
}

if(!exists("preciptemp")){
  preciptemp <- tempfile("precip", fileext = ".nc")
}

if(!file.exists(ettemp)){

  download.file(url = "https://www.dropbox.com/s/uyq9arqgnprxzv1/ET.nc?raw=1",
                destfile = ettemp,
                mode = "wb")
}

if(!file.exists(preciptemp)){

  download.file(url = "https://www.dropbox.com/s/sgmhq8cmth1jd8h/precip.nc?raw=1",
                destfile = preciptemp,
                mode = "wb")
}

precip_lowres <- stack(preciptemp)
names(precip_lowres) <- month.name


ET_stack <- stack(ettemp)
names(ET_stack) <- month.name


ui <- fluidPage(
  leafletOutput("map"),
  actionButton("go", "Go"),
  DT::dataTableOutput(outputId = "mytable")
)

server <- shinyServer(function(input, output, session) {

  output$map <- renderLeaflet({

    leaflet() %>%
      setView(lat = 35, lng = -100, zoom = 3) %>%
      addTiles(options = providerTileOptions(noWrap = TRUE)) 
  })

  clickValues <- reactiveValues(
    click=NULL, clat=NULL, clng=NULL)

  observeEvent(input$map_click, {
    clickValues$click <- input$map_click
    clickValues$clat <- click$lat
    clickValues$clng <- click$lng

    leafletProxy('map') %>%
      clearMarkers() %>% 
      addMarkers(lng=clickValues$clng, lat=clickValues$clat,
                 popup = paste(round(clickValues$click$lat, 2), 
                               round(clickValues$click$lng, 2)))

  })


  coordvals <- eventReactive(input$go, {

    coords <- data.frame(cbind(clickValues$clng, clickValues$clat))

    coordinates(coords) <- ~ X1 + X2

    precip_vals <- data.frame(raster::extract(precip_lowres, coords)) %>%
      gather(key = "Month", value = "Precip") %>%
      mutate(Precip = round(Precip, 0))

    ET_vals <- data.frame(raster::extract(ET_stack, coords)) %>%
      gather(key = "Month", value = "ET")

    combo_vals <- precip_vals %>%
      left_join(ET_vals) %>%
      mutate(ET = ET*3)

    combo_vals$Month <- factor(combo_vals$Month, levels = month.name)
  })

  output$mytable <- DT::renderDataTable({
    datatable(coordvals())
  })

})

shinyApp(ui, server)

Upvotes: 2

Related Questions