我有一个 Shiny 应用程序,我想在其中使用操作按钮添加 UI 元素,然后让插入的 ui 成为动态的。
这是我当前的 ui 文件:
library(shiny)
shinyUI(fluidPage(
div(id="placeholder"),
actionButton("addLine", "Add Line")
))
Run Code Online (Sandbox Code Playgroud)
和服务器文件:
library(shiny)
shinyServer(function(input, output) {
observeEvent(input$addLine, {
num <- input$addLine
id <- paste0("ind", num)
insertUI(
selector="#placeholder",
where="beforeBegin",
ui={
fluidRow(column(3, selectInput(paste0("selected", id), label=NULL, choices=c("choice1", "choice2"))))
})
})
})
Run Code Online (Sandbox Code Playgroud)
如果choice1
在特定的 ui 元素中选择了 ,我想textInput
在行中添加一个。如果choice2
在 ui 元素中选择了 ,我想添加一个numericInput
.
虽然我通常了解如何创建响应用户输入而改变的反应值,但我不知道在这里做什么,因为我不知道如何观察尚未创建的元素并且我不知道名称的。任何帮助将不胜感激!
tho*_*hal 11
代码
这可以通过模块轻松解决:
library(shiny)
row_ui <- function(id) {
ns <- NS(id)
fluidRow(
column(3,
selectInput(ns("type_chooser"),
label = "Choose Type:",
choices = c("text", "numeric"))
),
column(9,
uiOutput(ns("ui_placeholder"))
)
)
}
row_server <- function(input, output, session) {
return_value <- reactive({input$inner_element})
ns <- session$ns
output$ui_placeholder <- renderUI({
type <- req(input$type_chooser)
if(type == "text") {
textInput(ns("inner_element"), "Text:")
} else if (type == "numeric") {
numericInput(ns("inner_element"), "Value:", 0)
}
})
## if we later want to do some more sophisticated logic
## we can add reactives to this list
list(return_value = return_value)
}
ui <- fluidPage(
div(id="placeholder"),
actionButton("addLine", "Add Line"),
verbatimTextOutput("out")
)
server <- function(input, output, session) {
handler <- reactiveVal(list())
observeEvent(input$addLine, {
new_id <- paste("row", input$addLine, sep = "_")
insertUI(
selector = "#placeholder",
where = "beforeBegin",
ui = row_ui(new_id)
)
handler_list <- isolate(handler())
new_handler <- callModule(row_server, new_id)
handler_list <- c(handler_list, new_handler)
names(handler_list)[length(handler_list)] <- new_id
handler(handler_list)
})
output$out <- renderPrint({
lapply(handler(), function(handle) {
handle()
})
})
}
shinyApp(ui, server)
Run Code Online (Sandbox Code Playgroud)
解释
模块是一段模块化的代码,您可以随意重用它,而无需担心唯一名称,因为模块会在namespaces
.
一个模块由两部分组成:
UI
函数server
函数它们与 normalUI
和 server
functions非常相似,但需要注意以下几点:
namespacing
:在服务器中,您可以UI
像往常一样从 访问元素,例如input$type_chooser
。但是,在这UI
部分,您必须namespace
通过 using来处理元素,NS
它返回一个函数,您可以在其余代码中方便地使用该函数。为此,该UI
函数采用一个参数id
,该参数可以视为此模块的任何实例的(唯一)命名空间。该元素ids
在模块内必须是唯一的,并且由于命名空间,它们在整个应用程序中也将是唯一的,即使您使用模块的多个实例。UI
: 因为你UI
是一个函数,它只有一个 返回值,tagList
如果你想返回多个元素(这里不需要),你必须将元素包装在 a 中。server
:你需要session
参数,否则它是可选的。如果您希望您的模块与主应用程序进行通信,您可以传入一个(反应式)参数,您可以像往常一样在您的模块中使用该参数。类似地,如果您希望主应用程序使用模块中的某些值,您应该返回反应式,如代码所示。如果你想UI
从你的服务器函数中创建元素,你还需要命名它们,你可以通过session$ns
如图所示访问命名空间函数 。usage
:要使用您的模块,您可以UI
通过使用唯一的id
. 然后您必须调用callModule
以使服务器逻辑正常工作,在那里您传递相同的id
. 此调用的返回值是returnValue
您的模块服务器功能的 ,并且可以被起诉以使用来自模块内的值,也可以在主应用程序中使用。这简要地解释了模块。可以在这里找到一个非常好的教程,它更详细和完整地解释了模块。