Search code examples
rshinyr-leaflet

changing the destination on the map by the button shiny


I have a shiny app which displays a map and can choose a few countries based on the selectinput function. I'm trying to replace the selectInput with the button, so instead of choosing the country, the user should be able to click on the button and the next country will appear.

library(shiny)
library(leaflet)


df <- structure(list(lng = c(101.901875, -95.712891, 108.339537, 37.618423
), lat = c(35.486703, 37.09024, 14.315424, 55.751244), country = structure(c(1L, 
                                                                             3L, 4L, 2L), .Label = c("China", "Russia", "USA", "Vietnam"), class = "factor"), 
number = c(35500L, 6267L, 2947L, 3070L)), .Names = c("lng", 
                                                     "lat", "country", "number"), class = "data.frame", row.names = c(NA, 

                                                                                                                                                                                                                                            -4L))

ui <- (fluidPage(
  titlePanel(title = "countries"),
  sidebarLayout(
    sidebarPanel( uiOutput("countrynames"),
                  shiny::actionButton("dd", "click")
    ),
    mainPanel(leafletOutput("mymap", height = "500")
    ))
)
)

server <- function(input, output){
  output$countrynames <- renderUI({
    selectInput(inputId = "country", label = "Select a country to view it's values (you can choose more than one):",
                c(as.character(df$country)))
  })
  
  
  
  map_data <- reactive({
    data <- data.frame(df[df$country == input$country,])
    data$popup <- paste0(data$country, " ", data$number)
    return(data)
  })
  output$mymap <- renderLeaflet({
    leaflet(data = map_data()) %>%
      setView( lng = -16.882374406249937, lat = -1.7206857960062047, zoom = 0) %>%
      addProviderTiles( provider = "CartoDB.Positron") %>%
      addMarkers(lng = ~lng, lat = ~lat, popup = ~popup)
  })
}
shinyApp(ui, server)


Solution

  • You can achieve this with a reactiveVal to represent the index of the list of countries. It would update on the button's click.

    library(shiny)
    library(leaflet)
    
    countries = c("China", "Russia", "USA", "Vietnam")
    
    df <- structure(list(lng = c(101.901875, -95.712891, 108.339537, 37.618423
    ), lat = c(35.486703, 37.09024, 14.315424, 55.751244), country = structure(c(1L, 
                                                                                 3L, 4L, 2L), .Label = c("China", "Russia", "USA", "Vietnam"), class = "factor"), 
    number = c(35500L, 6267L, 2947L, 3070L)), .Names = c("lng", 
                                                         "lat", "country", "number"), class = "data.frame", row.names = c(NA, 
                                                                                                                          
                                                                                                                          -4L))
    
    ui <- (fluidPage(
      titlePanel(title = "countries"),
      sidebarLayout(
        sidebarPanel( 
          # uiOutput("countrynames"),
          shiny::actionButton("dd", "click")
        ),
        mainPanel(leafletOutput("mymap", height = "500")
        ))
    )
    )
    
    server <- function(input, output){
      output$countrynames <- renderUI({
        selectInput(inputId = "country", label = "Select a country to view it's values (you can choose more than one):",
                    c(as.character(df$country)))
      })
      
      
      index = reactiveVal(1)
      
      selected_country = reactive({
        
        countries[index()]
        
      })
      
      observeEvent(input$dd,{
        i = index() + 1
        if(i > length(countries)){
          i = 1
        }
        index(i)
      })
      
      map_data <- reactive({
        data <- data.frame(df[df$country == selected_country(),])
        data$popup <- paste0(data$country, " ", data$number)
        return(data)
      })
      output$mymap <- renderLeaflet({
        leaflet(data = map_data()) %>%
          setView( lng = -16.882374406249937, lat = -1.7206857960062047, zoom = 0) %>%
          addProviderTiles( provider = "CartoDB.Positron") %>%
          addMarkers(lng = ~lng, lat = ~lat, popup = ~popup)
      })
    }
    shinyApp(ui, server)
    

    To maintain the selectInput you could use an updateSelectInput.