我有许多输入都存在于使用conditionalPanel
在服务器端创建的同一renderUI
中。我不能将其移至用户界面,因为某些部分使用了反应对象。
我想做的是让一个输入确定另一输入的默认值。但是,由于这两者都存在于对renderUI
的同一调用中,因此它创建了循环依赖项,这使我无法选择除前一个输入的默认选项之外的任何内容。考虑以下示例app.R
文件:
library(shiny)
key <- c("a" = 1, "b" = 2, "c" = 3, "d" = 4)
ui <- fluidPage(
uiOutput("inputs")
)
server <- function(input, output) {
output$inputs <- renderUI(
tagList(
selectInput("input1", "Input 1:", letters[1:4]),
textInput("input2", "Input 2:", rval())
)
)
rval <- reactive(key[input$input1])
}
shinyApp(ui = ui, server = server)
我在全局环境中定义key
(在应用程序中,这是从全局中的.yaml文件读取的),然后uiOutput
向用户显示所有输入。我们可以看到input2
的默认值取决于为input1
选择的内容。发生的情况是input1
触发了rval()
的更改,进而触发了input2
的更改。还行吧。但是,由于input1
和input2
是在对renderUI
的同一调用中呈现的,因此input1
变得依赖于它自己,因此只要用户在其中选择另一个选项,它就会重置为默认值。下拉菜单。
我再次这样编码,因为两个输入在我正在使用的实际应用程序中存在于同一conditionalPanel
中(尽管在本示例中不是)。
我尝试用selectInput(...)
包围isolate()
,但这是行不通的。
如何将两个输入保留在相同的renderUI
中,但允许用户更改input1
而又不必依赖于自身并进行重置?
答案 0 :(得分:2)
您可以使用observeEvent(iunputs$input1, ...)
和updateTextinput
使input2
保持最新。使用这种方法的优点是您的UI不必经常重新渲染。
library(shiny)
key <- c("a" = 1, "b" = 2, "c" = 3, "d" = 4)
ui <- fluidPage(
uiOutput("inputs")
)
server <- function(input, output, session) {
output$inputs <- renderUI({
tagList(
selectInput("input1", "Input 1:", letters[1:4]),
textInput("input2", "Input 2:", "placeholder")
)
})
observeEvent(input$input1, {
mapped_input <- key[[req(input$input1)]]
updateTextInput(session, "input2", value = mapped_input)
})
}
shinyApp(ui = ui, server = server)
req
确保仅在updateTextInput
已经渲染的情况下调用output$inputs
。
我意识到在某些情况下,updateXXX
函数不足以呈现动态输入。在这种情况下,最好是在单独的renderUI
语句中生成UI,这样就不再需要循环性了。
注意:我不知道conditionalPanel
是如何使必须使用renderUI
的。如果您正在寻找在代码中使用抽象的方法,请改用Shiny Modules。