[英]R Shiny modules with conditionalPanel and reactives
我試圖模塊化一個復雜的Shiny應用程序,我有一個conditionalPanel
面板應該只出現給定一個輸入狀態。
在我將所有內容都模塊化之前,輸入和conditionalPanel都在ui.R
,我可以使用以下內容引用輸入:
conditionalPanel("input.select == 'Option one'", p('Option one is selected'))
現在我已經模塊化了,訪問輸入更加復雜。 我認為以下是這樣做的方法,但它並不是很有效。 (這里我把東西組合成一個獨立的腳本):
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)
我認為這應該有效,但它不起作用 - 它只有在我對主ui部分中output$selected
進行另一個引用時才有效:
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.'))
))
不幸的是,當然這會產生渲染textOutput('selected')
結果的不良影響。 我只能猜測它的工作原因是因為它以某種方式觸發反應,而JavaScript引用本身並沒有。
知道如何讓這個conditionalPanel正常工作嗎?
謝謝..
編輯:原來並不是一個錯誤: https : //github.com/rstudio/shiny/issues/1318 。 請看下面我自己的答案。
但是請注意,我實際上喜歡在接受的答案中給出的renderUI
解決方案比我原來的conditionalPanel
方法更好。
調用模塊后, selectizeInput
的ID為id1-select
。 在javaScript中,有兩種訪問對象屬性的方法:
objectName.property
或objectName['property']
由於存在-
在ID
,我們必須通過字符串引用它,所以第二個方法是路要走。
conditionalPanel中的conditionalPanel
變為:
input['id1-select'] == 'Option one'
完整示例:
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)
編輯:
這確實有效,但是它是否違反了模塊化的概念? 你必須知道模塊的代碼在內部調用輸入'select'以構造'id1-select'。
你是對的。
根據這篇文章 ,你使用的技巧,即將模塊調用分配給輸出$ selected,然后通過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)
原來它實際上不是一個bug,只是有點棘手。 據Joe Cheng說 ,
右 - 默認情況下,如果它們不可見,我們不會計算/渲染輸出值。 如果我們不計算它們,你就不能在條件下使用它們。
您可以通過設置每次計算輸出來更改此行為,您可以在服務器中使用它.R(將
outputId
替換為相應的值):
outputOptions(output, "outputId", suspendWhenHidden = FALSE)
因此,為了解決我的原始示例的問題,我們只需要將一行添加到服務器函數:
server <- shinyServer(function(input, output, session) {
output$selected <- callModule(selector, 'id1')
outputOptions(output, 'selected', suspendWhenHidden = FALSE) # Adding this line
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.