Reputation: 891
In my example I need to access leaflet
map from module 2 (nested) and use input$
on a map to return polygon coordinates. It works perfectly when I do this in my main module (module 1) where I can freely refer to 'map'. Unfortunately, when I pass map to another module (module 2) then the same trick with input$
doesn't work at all. Do you know how to solve it?
Here is the reproducible example. Please draw rectangle on a map and see that no coordinates are returned to the text area. But if you uncomment my gray code (in module 1) then you will see all works fine.
library(shiny)
library(mapboxer)
library(dplyr)
library(sf)
library(leaflet)
library(leaflet.extras)
moduleServer <- function(id, module) {
callModule(module, id)
}
# UI 1 #
mod_btn_UI1 <- function(id) {
ns <- NS(id)
tagList(
leafletOutput(ns("map")),
mod_btn_UI2(ns("other")),
verbatimTextOutput(ns("selectedArea1"))
)
}
# Server 1 #
mod_btn_server1 <- function(id){
moduleServer(id, function(input, output, session) {
ns <- NS(id)
coords <- quakes %>%
sf::st_as_sf(coords = c("long","lat"), crs = 4326)
output$map <- leaflet::renderLeaflet({
leaflet::leaflet() %>%
leaflet::addTiles() %>%
leaflet::setView(172.972965,-35.377261, zoom = 4) %>%
leaflet::addCircleMarkers(
data = coords,
stroke = FALSE,
radius = 6) %>%
leaflet.extras::addDrawToolbar()
})
# here I pass map id and session to module 2 and it works fine
mod_btn_server2("other", "map", session)
# # the code below works fine - here I simply pass 'map' to input$
#
# polygon_coords <- reactive({input$map_draw_new_feature$geometry$coordinates[[1]]})
# output$selectedArea1 <- renderPrint({
# print(polygon_coords())
# })
})
}
# UI 2 #
mod_btn_UI2 <- function(id) {
ns <- NS(id)
tagList(
verbatimTextOutput(ns("selectedArea2"))
)
}
# Server 2 #
mod_btn_server2 <- function(id, mapPassed, parentSession){
moduleServer(id, function(input, output, session) {
ns <- NS(id)
# here input seems not working with 'mapPassed' as it does in module 1
polygon_coords <- reactive({input$mapPassed_draw_new_feature$geometry$coordinates[[1]]})
output$selectedArea2 <- renderPrint({
print(polygon_coords())
})
})
}
# Final app #
ui <- fluidPage(
tagList(
mod_btn_UI1("test-btn"))
)
server <- function(input, output, session) {
mod_btn_server1("test-btn")
}
shinyApp(ui = ui, server = server)
Upvotes: 1
Views: 700
Reputation: 19544
Instead of passing the input name to the embedded module, you can pass it as a reactive:
mod_btn_server2("other",
reactive(input$map_draw_new_feature$geometry$coordinates[[1]]),
session)
and you use it in the embedded module like any other reactive :
polygon_coords <- reactive(mapPassed())
Upvotes: 1
Reputation: 2214
When you use this kind of modularization, input, output and sessions module parameters are subsets of main input/output/session that correspond to the namespace created from module id (the NS function). If you create an input named dummy in a module whose id is foo then what is really created is an input named foo-dummy. So in the foo module you get as input all inputs having names starting with "foo-" and similarly all outputs starting with "foo-".
Upvotes: 0