我试图模块化一个复杂的Shiny应用程序,我conditionalPanel应该只在给定某个输入状态时出现.
在我将所有内容都模块化之前,输入和conditionalPanel都在ui.R,我可以使用以下内容引用输入:
conditionalPanel("input.select == 'Option one'", p('Option one is selected'))
Run Code Online (Sandbox Code Playgroud)
现在我已经模块化了,访问输入更加复杂.我认为以下是这样做的方法,但它并不是很有效.(这里我把东西组合成一个独立的脚本):
library(shiny)
## Module code for 'selectorUI' and 'selector'
selectorUI <- function(id) {
ns <- NS(id)
selectizeInput(inputId = ns('select'),
label = 'Make a choice:',
choices = c('Option one', 'Option two'))
}
selector <- function(input, output, session) {
reactive(input$select)
}
## Main app
ui <- shinyUI(fluidPage(
selectorUI('id1'),
conditionalPanel(condition = "output.selected == 'Option one'", p('Option one is selected.'))
))
server <- shinyServer(function(input, output, session) {
output$selected <- callModule(selector, 'id1')
})
shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)
我认为这应该有效,但它没有 - 它只有在我output$selected在主ui部分做另一个引用时才有效:
ui <- shinyUI(fluidPage(
selectorUI('id1'),
textOutput('selected'), ## Adding just this one line makes the next line work
conditionalPanel(condition = "output.selected == 'Option one'", p('Option one is selected.'))
))
Run Code Online (Sandbox Code Playgroud)
不幸的是,这当然会产生渲染结果的不良影响textOutput('selected').我只能猜测它的工作原因是因为它以某种方式触发反应,而JavaScript引用本身并没有.
知道如何让这个conditionalPanel正常工作吗?
谢谢..
编辑:原来并不是一个错误:https://github.com/rstudio/shiny/issues/1318.请看下面我自己的答案.
但是请注意,我实际上更喜欢renderUI在接受的答案中给出的解决方案比我原来的conditionalPanel方法更好.
在调用模块后,ID selectizeInput为id1-select.在javaScript中,有两种访问对象属性的方法:
objectName.property 要么 objectName['property']
由于是-在ID我们通过字符串引用它,所以第二个方法是路要走.
条件conditionalPanel成为:
input['id1-select'] == 'Option one'
Run Code Online (Sandbox Code Playgroud)
完整示例:
library(shiny)
## Module code for 'selectorUI' and 'selector'
selectorUI <- function(id) {
ns <- NS(id)
selectizeInput(inputId = ns('select'),
label = 'Make a choice:',
choices = c('Option one', 'Option two'))
}
## Main app
ui <- shinyUI(fluidPage(
selectorUI('id1'),
conditionalPanel(condition = "input['id1-select'] == 'Option one'",
p('Option one is selected.'))
))
server <- shinyServer(function(input, output, session) {
})
shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)
编辑:
这确实有效,但是它是否违反了模块化的概念?你必须知道模块的代码在内部调用输入'select'以构造'id1-select'.
你是对的.
根据这篇文章,你使用的技巧,即将模块调用分配给选择的输出$然后在客户端通过output.selected它访问它的值应该可以工作,但事实并非如此.我不知道为什么......这可能是一个错误.(我有来自github的最新闪亮版本)
我唯一能想到的是使用renderUI而不是conditionalPanel如下例所示:
library(shiny)
## Module code for 'selectorUI' and 'selector'
selectorUI <- function(id) {
ns <- NS(id)
selectizeInput(inputId = ns('select'),
label = 'Make a choice:',
choices = c('Option one', 'Option two'))
}
selector <- function(input, output, session) {
reactive(input$select)
}
## Main app
ui <- shinyUI(fluidPage(
selectorUI('id1'),
uiOutput("dynamic1")
))
server <- shinyServer(function(input, output, session) {
output$dynamic1 <- renderUI({
condition1 <- callModule(selector, 'id1') # or just callModule(selector, 'id1')()
if (condition1() == 'Option one') return(p('Option one is selected.'))
})
})
shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)