R 闪亮 enable/disable UI 模块
RShiny enable/disable UI modules
我想将我的 Shiny 应用设置为根据用户输入动态 enable/disable UI 模块。我习惯于使用 ShinyJS 在非模块化应用程序中通过将 UI 元素的 ID 传递到 enable() 或 disable() 函数来执行此操作。但是,随着 UI 现在在模块内部生成,我无法再访问相同的 ID。
这是一个示例应用程序,每次单击“计数器 1”按钮时该应用程序递增 1。 “counterButton”功能包含在名为“counterModule.R”的外部模块中,我希望“toggleButton”能够在启用和禁用之间切换“counterButton”的状态。对 toggleState() 的调用目前没有执行任何我认为的操作,因为未找到“counter1”ID。解决此问题的最佳方法是什么?
app.R
library(shiny)
library(shinyjs)
ui <- fluidPage(
shinyjs::useShinyjs(),
mainPanel(actionButton(inputId = "toggleButton", label = "Toggle counter button"),
sidebarPanel(counterButton("counter1", "+1")))
)
server <- function(input, output, session) {
observeEvent(input$toggleButton, {
print("clicked toggle button")
shinyjs::toggleState("counter1")
})
counterServer("counter1")
}
shinyApp(ui, server)
R/counterModule.R
counterButton <- function(id, label = "Counter") {
ns <- NS(id)
tagList(
actionButton(ns("button"), label = label),
verbatimTextOutput(ns("out"))
)
}
counterServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
count <- reactiveVal(0)
observeEvent(input$button, {
count(count() + 1)
})
output$out <- renderText({
count()
})
count
}
)
}
你有两种可能。闪亮模块的命名空间采用以下格式:namespace-elementid
。这意味着您在模块中的按钮具有全局唯一的 ID counter1-button
(在模块中,您可以只使用 button
)。
因此,您可以在主 server
函数中使用命名空间 ID:
observeEvent(input$toggleButton, {
print("clicked toggle button")
shinyjs::toggleState("counter1-button")
})
但是,这以某种方式打破了模块和主服务器函数中定义的 ui/logic 的分离。因此,第二个选项是在主应用程序中定义切换按钮,但在模块中具有切换逻辑:
library(shiny)
library(shinyjs)
##########################
# code of the module
counterButton <- function(id, label = "Counter") {
ns <- NS(id)
tagList(
actionButton(ns("button"), label = label),
verbatimTextOutput(ns("out"))
)
}
counterServer <- function(id, toggle_action) {
moduleServer(
id,
function(input, output, session) {
count <- reactiveVal(0)
observeEvent(input$button, {
count(count() + 1)
})
output$out <- renderText({
count()
})
observeEvent(toggle_action(), {
print("clicked toggle button")
shinyjs::toggleState("button")
})
count
}
)
}
##########################
# code of the main app
ui <- fluidPage(
shinyjs::useShinyjs(),
mainPanel(actionButton(inputId = "toggleButton", label = "Toggle counter button"),
sidebarPanel(counterButton("counter1", "+1")))
)
server <- function(input, output, session) {
counterServer("counter1", toggle_action = reactive({input$toggleButton}))
}
shinyApp(ui, server)
我想将我的 Shiny 应用设置为根据用户输入动态 enable/disable UI 模块。我习惯于使用 ShinyJS 在非模块化应用程序中通过将 UI 元素的 ID 传递到 enable() 或 disable() 函数来执行此操作。但是,随着 UI 现在在模块内部生成,我无法再访问相同的 ID。
这是一个示例应用程序,每次单击“计数器 1”按钮时该应用程序递增 1。 “counterButton”功能包含在名为“counterModule.R”的外部模块中,我希望“toggleButton”能够在启用和禁用之间切换“counterButton”的状态。对 toggleState() 的调用目前没有执行任何我认为的操作,因为未找到“counter1”ID。解决此问题的最佳方法是什么?
app.R
library(shiny)
library(shinyjs)
ui <- fluidPage(
shinyjs::useShinyjs(),
mainPanel(actionButton(inputId = "toggleButton", label = "Toggle counter button"),
sidebarPanel(counterButton("counter1", "+1")))
)
server <- function(input, output, session) {
observeEvent(input$toggleButton, {
print("clicked toggle button")
shinyjs::toggleState("counter1")
})
counterServer("counter1")
}
shinyApp(ui, server)
R/counterModule.R
counterButton <- function(id, label = "Counter") {
ns <- NS(id)
tagList(
actionButton(ns("button"), label = label),
verbatimTextOutput(ns("out"))
)
}
counterServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
count <- reactiveVal(0)
observeEvent(input$button, {
count(count() + 1)
})
output$out <- renderText({
count()
})
count
}
)
}
你有两种可能。闪亮模块的命名空间采用以下格式:namespace-elementid
。这意味着您在模块中的按钮具有全局唯一的 ID counter1-button
(在模块中,您可以只使用 button
)。
因此,您可以在主 server
函数中使用命名空间 ID:
observeEvent(input$toggleButton, {
print("clicked toggle button")
shinyjs::toggleState("counter1-button")
})
但是,这以某种方式打破了模块和主服务器函数中定义的 ui/logic 的分离。因此,第二个选项是在主应用程序中定义切换按钮,但在模块中具有切换逻辑:
library(shiny)
library(shinyjs)
##########################
# code of the module
counterButton <- function(id, label = "Counter") {
ns <- NS(id)
tagList(
actionButton(ns("button"), label = label),
verbatimTextOutput(ns("out"))
)
}
counterServer <- function(id, toggle_action) {
moduleServer(
id,
function(input, output, session) {
count <- reactiveVal(0)
observeEvent(input$button, {
count(count() + 1)
})
output$out <- renderText({
count()
})
observeEvent(toggle_action(), {
print("clicked toggle button")
shinyjs::toggleState("button")
})
count
}
)
}
##########################
# code of the main app
ui <- fluidPage(
shinyjs::useShinyjs(),
mainPanel(actionButton(inputId = "toggleButton", label = "Toggle counter button"),
sidebarPanel(counterButton("counter1", "+1")))
)
server <- function(input, output, session) {
counterServer("counter1", toggle_action = reactive({input$toggleButton}))
}
shinyApp(ui, server)