目标和当前方法
我有一个模块,它可以删除自己的用户界面。我还希望能够从模块外部调用这个杀戮功能,因此我向模块的服务器逻辑传递了一个额外的反应,并在这个反应性触发时调用杀戮例程。
到现在为止,一直都还不错。现在,我想实现一个函数,它首先杀死我模块的所有实例,然后添加这个模块的新实例,这就是我所选择的设计的难点所在。
问题
我需要的是在我
input$add5
观察者添加任何新的实例,所有旧的实例都会被杀死。这可以通过设置
kill_switch(TRUE)
但问题是在
observer
在我的模块中可以对此作出反应,
输入$ADD5
观察者继续添加新的模块,这些模块将重置
kill_switch
到
FALSE
基本上,旧的例子永远不会被杀死。
基本上,在当前的设计中,我希望
观察者
在
基尔开关
在我更改标志后立即做出反应,只有在完成此操作后,我的
add5
观察者继续。
我需要什么
我认为我的设计不是最优的,因此任何关于如何在主应用程序和模块之间建立接口的建议都会受到高度赞赏。
代码
library(shiny)
boxer_ui <- function(id) {
ns <- NS(id)
div(
id,
id = ns("killme"),
style = "background-color:steelblue; font-size: xx-large; color: white")
}
boxer <- function(input, output, session, kill_switch) {
ns <- session$ns
observe({
req(kill_switch())
removeUI(paste0("#", ns("killme")))
})
}
ui <- fluidPage(actionButton("new", "new"),
actionButton("killall", "Kill All"),
actionButton("add5", "Kill All & Add 5"),
fluidRow(id = "content"))
server <- function(input, output, session) {
ids <- reactiveVal(0)
kill_switch <- reactiveVal(FALSE)
handler <- reactiveValues()
add_new <- function() {
kill_switch(FALSE)
ids(ids() + 1)
new_id <- paste0("id", ids())
insertUI("#content", "beforeEnd", boxer_ui(new_id))
handler[[new_id]] <- callModule(boxer, new_id, kill_switch)
}
observeEvent(input$new, {
isolate({
add_new()
})})
observeEvent(input$add5, {
isolate({
kill_switch(TRUE)
replicate(5, add_new())
})})
observeEvent(input$killall, kill_switch(TRUE))
}
shinyApp(ui, server)