0
votes

I'm working on a shiny app, which shows some markers on a leaflet map. When one of the markers is clicked, the corresponding row of the data.frame should be shown in a rhandsontable on the right of the map. In detail the map width should be decreased (e.g. from 100% to 50%) and in the free space the rhandsontable should be inserted.

There a some problems with my code, which I couldn't solve so far:

  1. Markers are not plotted on map when they are inside a leafletProxy (which is necessary in a more complex app).

  2. Only the first marker click is observed, then the table does not change anymore (probably something wrong with observeEvent)

  3. the rhandsontable is added below the map, not in the space to the right, which gets free, when the map width is reduced.

The data should be stored in a reactive value (to make changes possible).

Here is a minimal reproducible example:

library(shiny)
library(leaflet)
library(rhandsontable)

ui <- fluidPage(
  fluidRow(
    uiOutput("map2"), 
    uiOutput("table2")
  )
)


server <- function(input, output, session){
  values <- reactiveValues(
    data = data.frame(X = c(1, 2), lat = c(48, 49), lng = c(11, 11.5)),
    which_marker = NULL,
    leaflet_map_width = "100%"
  )

  output$map2 <- renderUI({
    leafletOutput("map", width = values$leaflet_map_width, height = "500px")
  })

  output$map <- renderLeaflet({
    leaflet() %>% addTiles() %>% setView(11, 48.5, 8) # %>% addMarkers(data = values$data, layerId = values$data$X)
  })

  observe({
    leafletProxy("map") %>% addMarkers(data = values$data, layerId = values$data$X)
  })

  observeEvent(input$map_marker_click, {
    print("observed map_marker_click")
    values$which_marker <- input$map_marker_click$id
    values$leaflet_map_width = "50%"
    output$table2 <- renderUI({
      rHandsontableOutput("table")
    })
  })

  output$table <- renderRHandsontable({
    data <- values$data[values$which_marker, ]
    rhandsontable(t(data), rowHeaderWidth = 120)
  })
}

shinyApp(ui, server)
1
Concerning 3) you should use sthg like: fluidRow( column(width = 10, offset = 0, style='padding:0px;', leafletOutput("map", width = "100%", height = "500px")), column(width = 2, offset = 0, style='padding:0px;', rHandsontableOutput("table") ) ) and set the width of the columns according to your needs.Tonio Liebrand
The problem with column is, that it preallocates space. So if I use the code you suggested, there will be white space initially to the right of the map (2/12 of the overall width). But I want to have the map using the full width initially and only when a marker is clicked should some of the width of the map be used for the rhandsontable instead. Hope, this makes it clear.needRhelp

1 Answers

1
votes

Note: This answers only 1/3 of the questions. But as one can see in the comments it does not make sense to give hints there: To answer your third questions see a solution below. (set the width of the columns according to your needs)

library(shiny)
library(leaflet)
library(rhandsontable)

ui <- fluidPage(
  uiOutput("map2")
)


server <- function(input, output, session){
  values <- reactiveValues(
    data = data.frame(X = c(1, 2), lat = c(48, 49), lng = c(11, 11.5)),
    which_marker = NULL,
    leaflet_map_width = "100%"
  )

  observe({
    values$which_marker <- input$map_marker_click$id
  })

  output$map2 <- renderUI({
    if(!is.null(input$map_marker_click)){
      fluidRow(
        column(width = 10, offset = 0, style='padding:0px;',
          leafletOutput("map", width = "100%", height = "500px")),
        column(width = 2, offset = 0, style='padding:0px;',
          rHandsontableOutput("table")
        )
      )
    }else{
      leafletOutput("map", width = values$leaflet_map_width, height = "500px")
    }

  })

  output$map <- renderLeaflet({
    leaflet() %>% addTiles() %>% addMarkers(data = values$data, layerId = values$data$X)
  })

  output$table <- renderRHandsontable({
    data <- values$data[values$which_marker, ]
    rhandsontable(t(data), rowHeaderWidth = 120)
  })
}

shinyApp(ui, server)