Search code examples
rshinyr-leaflet

Shiny + Leaflet reactive function not working


My data consists of columns like lon , lat, region, flat-type and year. I have used leaflet and shiny to create a map with cluster markers.

I included 2 selectInput boxes - one for year and one for the flat-type. Using the reactive function, it keeps giving me this error whenever I run the shiny app.

Error: Don't know how to get location data from object of class reactiveExpr,reactive

Here's my code

library(shiny)
library(leaflet)
library(dplyr)

ui <- fluidPage(
    titlePanel("Transactions for Resale Flats"),
    h3("Model A Flats: 3-Room, 4-Room, 5-Room"),
    sidebarLayout(position = 'right',
        sidebarPanel(
            selectInput("year","Year", choices = c("2007","2008",
                                                   "2009","2010","2011",
                                                   "2012","2013","2014",
                                                   "2015","2016","2017"), selected="2007"),
            
            selectInput("type","Flat-Type",choices = c("3 ROOM",'4 ROOM',"5 ROOM"),selected = "3-Room"),
            width = 2),
        mainPanel(leafletOutput("mymap",height = 650,width=605)))
    
    
)


server <- function(input,output, session){
    
    headlinedata<-reactive({
        headlinedata%>%
            filter(year %in% input$year & flat_type %in% input$type)
    })
    
    output$mymap <- renderLeaflet({
        leaflet(data=headlinedata) %>% 
            addTiles() %>% 
            addMarkers(clusterOptions = markerClusterOptions(),
            label = paste(headlinedata$address,',',headlinedata$town))

          })

    observe(leafletProxy('mymap', data=headlinedata()))%>%
    clearMarkers()%>%
    addMarkers(clusterOptions = markerClusterOptions(),
               label = paste(headlinedata$address,',',headlinedata$town))
    
}

shinyApp(ui = ui, server = server)

Also this code

  observe(leafletProxy('mymap', data=headlinedata()))%>%
        clearMarkers()%>%
        addMarkers(clusterOptions = markerClusterOptions(),
                   label = paste(headlinedata$address,',',headlinedata$town))

Whenever I include this, the app will run for a second and then close immediately. This code is supposed to update the map markers whenever the input changes.


Solution

  • First, you need to refer to reactive variables as the variable name followed by (). In output$mymap, you refer to headlinedata, which is the data frame to be filtered, when it should be headlinedata(), which is the reactive variable that's already been filtered. To disambiguate the two, I changed the name of the reactive variable to df. Then, when that reactive variable is needed in code downstream, I refer to it as df().

    Second, since df() is a reactive variable and we've set up the leaflet to depend upon it, whenever the reactive variable changes, the map will also change. This means we don't need the observe(leafletProxy ... code.

    Here's a reproducible example you can copy and paste.

    library(shiny)
    library(leaflet)
    library(dplyr)
    
    set.seed(1)
    headlinedata <- data.frame(year = rep(2007:2017, 10),
                               flat_type = sample(c("3 ROOM",'4 ROOM',"5 ROOM"),
                                             110, replace=T),
                               lat = sample(1:50,  110, replace=T),
                               lng = sample(1:50, 110, replace=T),
                               address = "address", 
                               town = "town")
    
    ui <- fluidPage(
        titlePanel("Transactions for Resale Flats"),
        h3("Model A Flats: 3-Room, 4-Room, 5-Room"),
        sidebarLayout(position = 'right',
                      sidebarPanel(
                          selectInput("year","Year", choices = c("2007","2008",
                                                                 "2009","2010","2011",
                                                                 "2012","2013","2014",
                                                                 "2015","2016","2017"), selected="2007"),
    
                          selectInput("type","Flat-Type",choices = c("3 ROOM",'4 ROOM',"5 ROOM"),selected = "3-Room"),
                          width = 2),
                      mainPanel(leafletOutput("mymap",height = 650,width=605)))
    
    
    )
    
    
    server <- function(input,output, session){
    
        df<-reactive({
            headlinedata%>%
                dplyr::filter(year %in% input$year & flat_type %in% input$type)
        })
    
        output$mymap <- renderLeaflet({
            leaflet(data=df()) %>% 
                addTiles() %>% 
                addMarkers(clusterOptions = markerClusterOptions(),
                           label = paste(df()$address,',',df()$town))
    
        })
    
    
    }
    
    shinyApp(ui = ui, server = server)