How to make polygons clickable?

47 Views Asked by At

enter image description here

I am trying to make a leaflet output, where I can click the neighbor boundaries (in red) that are visible initially on selecting a city. The clicking should generate all the polygons in that neighborhood with blue boundaries. My code is working fine except that when I click another neighborhood, the polygons of the previously selected neighborhood will still be there and these previously selected neighborhoods are not clickable anymore.

What, I am trying to get here is when I select the next neighborhood's boundary, the polygons of the last selected boundary disappear and all the neighborhood boundaries remain clickable.

Here is the server code that I am using

# SERVER
server <- function(input, output) {
  
  current_neighborhood <- reactiveVal(NULL)
  previous_neighborhood <- reactiveVal(NULL)
  
  output$dynamic_bg <- renderUI({
    city_choice <- tolower(input$city)  # Convert the city name to lowercase
    css_str <- paste0("
      body {
        background-image: url('background", city_choice, ".jpg');
        background-size: cover;
        background-repeat: no-repeat;
        background-attachment: fixed;
      }
    ")
    tags$style(HTML(css_str))
  })
  
  # Reactive expression that filters the Geojson_sf_list based on the selected city
  filtered_sf_list <- reactive({
    indices <- which(cleaned_data$residing_city == input$city)
    list(sf_objects = geojson_sf_list[indices], neighborhoods = cleaned_data$NeighborhoodName[indices])
  })
  
  output$map <- renderLeaflet({
    map <- leaflet() %>% addTiles() %>%
      setView(lng = -73.9939, lat = 40.7336, zoom = 12)
    
    # Extracting the filtered data
    sf_objects <- filtered_sf_list()$sf_objects
    neighborhoods <- filtered_sf_list()$neighborhoods
    
    # Add each neighborhood to the map for the selected city with popups
    for (i in seq_along(sf_objects)) {
      sf_obj <- sf_objects[[i]]
      neighborhood_name <- neighborhoods[i]
      
      map <- map %>% addPolygons(data = sf_obj, color = "red", weight = 1, 
                                 fill = FALSE,
                                 label = as.character(neighborhood_name),
                                 highlightOptions = highlightOptions(color = "#000000", bringToFront = TRUE, weight = 2),
                                 layerId = as.character(neighborhood_name)  # Assign layerId for click event
      )
    }
    
    # If there are polygons for the selected city, zoom to their bounds
    if(length(sf_objects) > 0) {
      bounds <- lapply(sf_objects, st_bbox)
      all_bounds <- do.call(rbind, bounds)
      map <- map %>% fitBounds(
        lng1 = min(all_bounds[, "xmin"]),
        lat1 = min(all_bounds[, "ymin"]),
        lng2 = max(all_bounds[, "xmax"]),
        lat2 = max(all_bounds[, "ymax"])
      )
    }
    
    map
  })
  
  observeEvent(input$map_shape_click, {
    click_data <- input$map_shape_click
    clicked_neighborhood <- click_data$id
    
    # Store the current clicked neighborhood
    previous_neighborhood(current_neighborhood())
    current_neighborhood(clicked_neighborhood)
    
    proxy <- leafletProxy("map")
    
    # Reset the previously clicked neighborhood, if any
    if (!is.null(previous_neighborhood())) {
      indices_prev <- which(cleaned_data$NeighborhoodName == previous_neighborhood())
      sf_objects_prev <- geojson_sf_list[indices_prev]
      
      for (sf_obj in sf_objects_prev) {
        proxy %>% addPolygons(data = sf_obj, color = "red", weight = 1, fill = FALSE)
      }
    }
    
    # Highlight the currently clicked neighborhood
    indices <- which(cleaned_data$NeighborhoodName == clicked_neighborhood)
    selected_sf_objects <- geojson_sf_list[indices]
    
    for (sf_obj in selected_sf_objects) {
      proxy %>% addPolygons(data = sf_obj, color = "blue", weight = 1, fill = FALSE)
    }
  })
  
}

shinyApp(ui, server)

0

There are 0 best solutions below