下面的应用程序包含一个selectInput
( input$month
) 和一个按钮 ,Show Modal
单击时会启动一个模式窗口。模式包含一个按钮,Add UI
插入一些文本,Element x
其中x
是计数器的值,每次Add UI
单击时增加 1。
打开模式窗口的应用程序启动时的屏幕截图:
该应用程序是模块化的,因此与模式关联的 UI 由 function 呈现,modUI
相应的服务器逻辑在 function 中定义modServer
。modUI
每次input$month
更改以覆盖先前插入的文本元素时都会重新呈现。
我需要以编程方式插入第一块文本,以便在应用加载或用户更改input$month
时,Element 1
已经在模式中呈现:
为此,我试图让 insertUI 观察者在input$add_ui
大于或等于 0 时触发 - 即observeEvent(if(req(input$add_ui) >= 0) TRUE else return(), { #insertUI expr })
。但是,这不起作用,我不明白为什么。由于观察者被热切地评估,这个观察者不应该在input$add_ui
完成初始化后触发吗?
每次input$month
更改时,计数器也必须重置为 0,以便插入的文本元素从 开始Element 1
。为此,我将以下观察者包括在modServer
:
observe({
req(input$add_ui == 0) #checking that modUI has finished rerendering
print(paste('month changed to:', month, 'resetting counter'));
counter(0)
})
req(input$add_ui == 0)
检查是否已完成重新渲染,modUI
并且仅在检查通过时才重置计数器。但是我觉得这使得它modServer
不那么自给自足,并且想知道是否有一种不那么迂回的方式?
最后,我对模块比较陌生,想知道是否有人可以解释为什么在通过调用 counter()
时不自动重置?modServer
observe(callModule(modServer, 'hi', month = input$month))
如果模块有自己的环境,为什么它的价值仍然存在?
我将不胜感激任何帮助,因为我已经坚持了一段时间。
重现上述内容的代码:
library(shiny)
library(shinyBS)
#MODULE UI ----
modUI <- function(id) {
ns <- NS(id)
tagList(
actionButton(ns("show_modal"), "Show modal"),
bsModal(
id = ns('modal'),
trigger = ns('show_modal'),
actionButton(ns("add_ui"), "Add UI"),
tags$div(id = ns("placeholder1"))
)
)
}
#MODULE SERVER ----
modServer <- function(input, output, session, month) {
ns <- session$ns
counter <- reactiveVal(0)
# Observer to insert UI element
observeEvent(if(req(input$add_ui) >= 0) TRUE else return(), {
counter(counter() + 1)
insertUI(
selector = paste0("#", ns("placeholder1")),
ui = tags$div(paste('Element', counter()))
)
})
# Reset counter() if month is changed
observe({
req(input$add_ui == 0)
print(paste('month changed to:', month, 'resetting counter'));
counter(0)
})
# Print
observe({ print(paste('input$add_ui:', input$add_ui, 'counter:', counter())) })
}
#MAIN UI ----
ui <- fluidPage(
tagList(
selectInput('month', 'Month', month.abb),
uiOutput('modal_ui')
)
)
#MAIN SERVER ----
server <- function(input, output, session) {
#Call modUI if input$month is changed
observe(callModule(modServer, 'hi', month = input$month))
#Rerender modUI if input$month is changed
output$modal_ui <- renderUI({
input$month
modUI('hi')
})
observe(print(input$month))
}
shinyApp(ui = ui, server = server)