0

For some reason I need to nest modules. I passed button to nested module mod_coordinates_server but when I click the button points do not show up on the map. I used here reactive and button is passed correctly - when you uncomment print(btn()) (in observeEvent) you'll see that values are returned to console properly. It means that button works corectly. So why it doesn't work for points? Is it something wrong with namespace?

Below working example:

library(shiny)
library(mapboxer)
library(dplyr)
library(sf)


moduleServer <- function(id, module) {
    callModule(module, id)
}

# UI #
mod_btn_UI <- function(id) {
    
    ns <- NS(id)
    tagList(
        actionButton(ns("btn"), "Click me!"),
        mod_coordinates_UI(ns("proxyMap"))
    )
}

# Server #
mod_btn_server <- function(id){
    moduleServer(id, function(input, output, session) {

        btn <- reactive({input$btn})
        mod_coordinates_server("proxyMap", btn)
        
    })
}


# Module Coordinates

mod_coordinates_UI <- function(id) {
    
    ns <- NS(id)
    tagList(
        mapboxerOutput(ns("map"))
    )
}


mod_coordinates_server <- function(id, btn){
    moduleServer(id, function(input, output, session) {
        
        ns <- NS(id)
        
        coords <- quakes %>%
            sf::st_as_sf(coords = c("long","lat"), crs = 4326)
        
        output$map <- mapboxer::renderMapboxer({
            mapboxer::mapboxer(
                style = mapboxer::basemaps$Mapbox$light_v10,
                center = c(174.387636,-33.543557),
                pitch = 5,
                padding = 0,
                zoom = 3)
        })
        
        observeEvent(btn(), {
            # print(btn())
            mapboxer::mapboxer_proxy(ns("map")) %>%
                mapboxer::add_circle_layer(
                    id = "xyz",
                    source = mapboxer::as_mapbox_source(coords),
                    circle_color = "#952444",
                    circle_opacity = 0.7,
                    circle_radius = 6
                ) %>%
                mapboxer::update_mapboxer()
        })        
       
    })
 }


# FINAL App #

ui <- fluidPage(
    
    tagList(
        mod_btn_UI("test-btn"))
)

server <- function(input, output, session) {
    
    mod_btn_server("test-btn")
    
}

shinyApp(ui = ui, server = server)
mustafa00
  • 751
  • 1
  • 7
  • 28

1 Answers1

1

Call the second module also in the main app. Try this

moduleServer <- function(id, module) {
  callModule(module, id)
}

# UI #
mod_btn_UI <- function(id) {
  
  ns <- NS(id)
  tagList(
    actionButton(ns("btn"), "Click me!")
    
  )
}

# Server #
mod_btn_server <- function(id){
  moduleServer(id, function(input, output, session) {
    
    reactive({input$btn})
    # mod_coordinates_server("proxyMap", btn)
    
  })
}

# Module Coordinates

mod_coordinates_UI <- function(id) {
  
  ns <- NS(id)
  tagList(
    mapboxerOutput(ns("map"))
  )
}

mod_coordinates_server <- function(id, btn){
  moduleServer(id, function(input, output, session) {
    
    ns <- session$ns
    
    coords <- quakes %>%
      sf::st_as_sf(coords = c("long","lat"), crs = 4326)
    
    output$map <- mapboxer::renderMapboxer({
      mapboxer::mapboxer(
        style = mapboxer::basemaps$Mapbox$light_v10,
        center = c(174.387636,-33.543557),
        pitch = 5,
        padding = 0,
        zoom = 3)
    })
    
    observeEvent(btn(), {
      print(btn())
      mapboxer::mapboxer_proxy(ns("map")) %>%
        mapboxer::add_circle_layer(
          id = "xyz",
          source = mapboxer::as_mapbox_source(coords),
          circle_color = "#952444",
          circle_opacity = 0.7,
          circle_radius = 6
        ) %>%
        mapboxer::update_mapboxer()
    })        
    
  })
}


# FINAL App #

ui <- fluidPage(
  
  tagList(
    mod_btn_UI("test-btn"), 
    mod_coordinates_UI("proxyMap")
    )
)

server <- function(input, output, session) {
  
  btn <- mod_btn_server("test-btn")
  mod_coordinates_server("proxyMap", btn)
}

shinyApp(ui = ui, server = server)

If you wish to maintain nesting, try this

library(shiny)
library(mapboxer)
library(dplyr)
library(sf)

Sys.setenv(MAPBOX_API_TOKEN = "pk.eyJ1IjoiaHdsIiwiYSI6ImNramJxY2YxcDV2YXoyeW40YXlvbmUyazQifQ.7HBEvMyrAnVpkKO7MNH7ww")

moduleServer <- function(id, module) {
  callModule(module, id)
}

# UI #
mod_btn_UI <- function(id) {
  
  ns <- NS(id)
  tagList(
    actionButton(ns("btn"), "Click me!"),
    mod_coordinates_UI(ns("proxyMap"))
  )
}

# Server #
mod_btn_server <- function(id){
  moduleServer(id, function(input, output, session) {
    
    # btn <- reactive({input$btn})
    mod_coordinates_server("proxyMap", reactive({input$btn}))
    
  })
}


# Module Coordinates

mod_coordinates_UI <- function(id) {
  
  ns <- NS(id)
  tagList(
    mapboxerOutput(ns("map"))
  )
}


mod_coordinates_server <- function(id, btn){
  moduleServer(id, function(input, output, session) {
    
    ns <- session$ns
    
    coords <- quakes %>%
      sf::st_as_sf(coords = c("long","lat"), crs = 4326)
    
    output$map <- mapboxer::renderMapboxer({
      mapboxer::mapboxer(
        style = mapboxer::basemaps$Mapbox$light_v10,
        center = c(174.387636,-33.543557),
        pitch = 5,
        padding = 0,
        zoom = 3)
    })
    
    observeEvent(btn(), {
      # print(btn())
      mapboxer::mapboxer_proxy(ns("map")) %>%
        mapboxer::add_circle_layer(
          id = "xyz",
          source = mapboxer::as_mapbox_source(coords),
          circle_color = "#952444",
          circle_opacity = 0.7,
          circle_radius = 6
        ) %>%
        mapboxer::update_mapboxer()
    })        
    
  })
}


# FINAL App #

ui <- fluidPage(
  
  tagList(
    mod_btn_UI("test-btn"))
)

server <- function(input, output, session) {
  
  mod_btn_server("test-btn")
  
}

shinyApp(ui = ui, server = server)

output

YBS
  • 19,324
  • 2
  • 9
  • 27
  • Thanks, it works. However don't know why nested module didn't work here. Nesting is quite common mechanism in shiny apps, that's why I wanted to use it. – mustafa00 Mar 20 '21 at 17:05
  • 1
    @mustafa00, to maintain nesting, just use `ns <- session$ns` on the server side. Please try the updated code. – YBS Mar 20 '21 at 18:07