简体   繁体   中英

Modularizing R Shiny code: ObserveEvent function in module

I am trying to improve the usability of my app.R code in R Shiny which is getting very long.

Essentially, I'd like to create a module (infras.R) to contain a large number of observeEvent functions that are linked to checkboxInputs.

I understand I need to source the module in app.R, wrap the observeEvent in a function, include namespaces (ns) for input IDs in the observeEvent function and insert a callModule for the function. I've also wrapped the callModule in an ObserveEvent so that its functionality persists and does not trigger only once after starting the webapp.

The following error is output on running app.R but I'm not sure how to resolve:

Warning: Error in proxy: could not find function "proxy"
   81: eval
   80: eval
   79: %>%
   78: module [infras.R#153]
   73: callModule
   72: observeEventHandler  
    1: runApp

Thanks for your assistance with this as I've found it challenging to find literature on how to do this.

Key snippets from my R scripts.

infras.R (updated):

icons_pow <- awesomeIcons(
  iconColor = 'white',
  markerColor = 'green',
  text = "m"
)

mod <- function(input, output, session, pow_id, prox){

observeEvent(pow_id(),{
  if(pow_id() != 0){
     pow_id <- readOGR("../geospatial_files/ind", layer = "plants")
     pow_iddf <- as.data.frame(pow_id)
     prox %>%
       addAwesomeMarkers(lng=pow_iddf$coords.x1, lat=pow_iddf$coords.x2, group = "pow_idg", icon=icons_pow,
                    label = paste(pow_iddf$Name,pow_iddf$Power_type,sep = ", "))
  }
  else {prox %>% clearGroup("pow_idg") %>% removeControl(layerId="pow_idc")
  }
}
)
}

app.R (updated):

...
source("infras.R")
...

server <- function(input, output, session) {
...

proxy <- leafletProxy("map")
callModule(mod, "mod", reactive(input$pow_id), proxy)


  })
...

}

You need to wrap your input object into a reactive and use that as an input argument to your module. The other input argument is your leaflet proxy. Inside the module, you can use observe to change your proxy, which is then instantly updated:

library(shiny)
library(leaflet)
library(RColorBrewer)

# The module containing the observer. Input is the reactive handle of legend input and the proxy
mod <- function(input, output, session, legend, prox){

  observe({
    prox %>% clearControls()
    if (legend()) {
      prox %>% addLegend(position = "bottomright",
                            pal = colorNumeric("Blues", quakes$mag), values = ~mag
      )
    }
  })

}

ui <- bootstrapPage(
  checkboxInput("legend", "Show legend", TRUE),
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  leafletOutput("map", width = "100%", height = "100%")
)

server <- function(input, output, session) {

  output$map <- renderLeaflet({
    pal <- colorNumeric("Blues", quakes$mag)
    leaflet(quakes) %>% addTiles() %>%      
      addCircles(radius = ~10^mag/10, weight = 1, color = "#777777",
                 fillColor = ~pal(mag), fillOpacity = 0.7, popup = ~paste(mag)) %>% 
      fitBounds(~min(long), ~min(lat), ~max(long), ~max(lat))
  })

  # This is the handle for map
  proxy <- leafletProxy("map", data = quakes)
  callModule(mod, "mod", reactive(input$legend), proxy)


}

shinyApp(ui, server)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM