我一直在钻研Shiny模块,到目前为止,一切都很顺利。但是,我在处理来自另一个模块的inputId时遇到了麻烦。具体来说,我想使用shinyjs::disable这样的函数,通过按下一个模块中的按钮来禁用另一个模块中的按钮(numericInput、selectizeInput等也是如此)。
我考虑过使用R6,但考虑到它的简单性,它可能会给应用程序增加不必要的复杂性。尽管如此,我还是愿意接受涉及或不涉及R6/石像鬼方法的建议。
这里有一个玩具的例子,总结了这个问题和我已经尝试到目前为止。
selectUI <- function(id) {
ns <- NS(id)
tagList(
fluidRow(
column(width = 4, offset = 0, align = "center",
selectizeInput(inputId = ns("item"),
label = "selection",
choices = c("", "a", "b", "c"),
selected = "")
),
column(width = 8, offset = 0)
)
)
}
selectServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
return (
list(
selection = shiny::reactive(input$item)
)
)
}
)
}
buttonUI <- function(id) {
ns <- NS(id)
tagList(
fluidRow(
column(width = 2, offset = 0, align = "center",
circleButton(inputId = ns("btn"))
),
column(width = 10, offset = 0)
))
}
buttonServer <- function(id, item) {
moduleServer(
id,
function(input, output, session) {
observeEvent(
eventExpr = input$btn,
handlerExpr = {
#' does not work, i've tried with item(), item()$inputId, item$inputId()
#' and also hardcoding the id with and without the ns prefix ("item", "select-item", "button-select-item")
shinyjs::disable("item") # the issue ----
},
ignoreNULL = TRUE,
ignoreInit = TRUE
)
#'debug
observe({
#' input from module selectUI & selectServer identified correctly
showNotification(item(), duration = 5)
})
}
)
}
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
selectUI(id = "select"),
buttonUI(id = "button"),
)
server <- function(input, output, session) {
item <- selectServer(id = "select")
buttonServer(id = "button", item = item$selection)
}
shinyApp(ui, server)
欢迎提出任何意见或建议。
1条答案
按热度按时间wgx48brx1#
这里有一个使用
gargoyle
的解决方案,因为它是一个非常简单的解决方案,通常可以工作。gargoyle
包只是一个很好的 Package 器,它围绕着session$userData
对象中reactiveVal
的使用。另一种方法是将被动式从一个模块传递到另一个模块。这也可以很好地工作,但当你想像这里一样管理多个“更新信号”时(即当模块中的某个地方发生了什么事情时,禁用/启用UI的某些部分),这就成了一个问题。