简体   繁体   English

模块化R Shiny代码:模块中的ObserveEvent函数

[英]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. 我正在尝试提高我的app.R代码在R Shiny中的可用性,这已经变得很长了。

Essentially, I'd like to create a module (infras.R) to contain a large number of observeEvent functions that are linked to checkboxInputs. 从本质上讲,我想创建一个模块(infras.R),以包含链接到checkboxInputs的大量watchEvent函数。

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. 我了解我需要在app.R中获取模块,将observeEvent包装在函数中,在observeEvent函数中包含输入ID的名称空间(ns),并为该函数插入callModule。 I've also wrapped the callModule in an ObserveEvent so that its functionality persists and does not trigger only once after starting the webapp. 我还将callModule封装在ObserveEvent中,以便其功能持久存在,并且不会在启动Webapp后仅触发一次。

The following error is output on running app.R but I'm not sure how to resolve: 在运行app.R时输出以下错误,但我不确定如何解决:

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. 我的R脚本中的关键片段。

infras.R (updated): infras.R(更新):

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): app.R(已更新):

...
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. 您需要将input对象包装为reactive并将其用作模块的输入参数。 The other input argument is your leaflet proxy. 另一个输入参数是您的传单代理。 Inside the module, you can use observe to change your proxy, which is then instantly updated: 在模块内部,您可以使用observe更改代理,然后立即对其进行更新:

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)

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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