rshinygisr-leaflet

Change setView dynamically according to select box in R shiny app


I'm developing a leaflet map in R shiny. In this app I want the focus of the map to be changed whenever the lng and lat value in setView() is changed. The lng and lat values are based on what country I select from a drop down box. Previously I use static value for lng and lat in an ifelse() function and the app works. But now the problem is when I want to make things more generic: the lng and lat will be the mean of the longitude and latitude from a subset of the data with the chosen country, the app doesn't show map anymore (from my point of view the calculation seems right)

Below is the simplified and workable R script:

global.R:

library(devtools)
library(leaflet)
library(htmlwidgets)
library(shiny)
library(shinydashboard)
library(sp)
library(rworldmap)
library(RCurl)
library(ggmap)

df <- read.csv(url("https://docs.google.com/spreadsheets/d/1rrEJiuxr4nafTqUQBlPpUdGwvGeGtBJExlPJdday2uw/pub?output=csv"),
           header = T,
           stringsAsFactors = F)
df$Time <- as.Date(df$Time, "%d/%m/%Y")

ui.R

header <- dashboardHeader(
  title = 'Shiny Memery'
)
body <- dashboardBody(
  fluidRow(
    tabBox(
      tabPanel("My Map", leafletOutput("mymap",height = 550)),
      width = 700
    ))
)
dashboardPage(
  header,
  dashboardSidebar(
    sliderInput('Timeline Value','Time line',min = min(df$Time),
                max = max(df$Time), 
                value = c(min(df$Time), min(df$Time)+10)),
    selectInput("select_country", label = "Select Country", 
                choices = NULL, 
                selected = NULL)
  ),
  body
)

server.R

  shinyServer(function(input, output, session) {
  
  dfs <- reactive({
    tmp <- subset(df, df$Time <= input$`Timeline Value`[2] & df$Time >= input$`Timeline Value`[1])  
    tmp
  })
  
  part_choices <- reactive({
    as.list(c("All",  unique(as.character(dfs()$Country))))
  })
  
  observe({
    updateSelectInput(session, "select_country", choices=part_choices())
  })

  output$mymap <- renderLeaflet({
    lng <- ifelse(input$select_country == "All", mean(dfs()$lon),
                  mean(subset(dfs(), Country %in% input$select_country)$lon)
                         )
    lat <- ifelse(input$select_country == "All", mean(dfs()$lat),
                  mean(subset(dfs(), Country %in% input$select_country)$lat)
                         )
 
    m <- leaflet(dfs()) %>%
      addTiles(
      ) %>%  
      setView(lng, lat, zoom = 5) %>%
      addMarkers(~lon, ~lat, 
                 clusterOptions = markerClusterOptions())
  })
})

You will see in the server.R part I use ifelse() to change the lng and lat value that later can be used in setView() function. After I changed the else argument into a calculation the app doesn't work anymore.


Solution

  • In your ui.R, try changing your country input to

    selectInput("select_country", label = "Select Country", 
                choices = "All", 
                selected = "All")
    

    My guess is that the ifelses do not return a number, given that input$select_country is initialized at NULL, which (for reasons that are unclear to me) causes both renderLeaflet and updateSelectInput not to run, preventing the country selector from being updated.