R带条件面板和反应堆的Shiny模块 [英] R Shiny modules with conditionalPanel and reactives

查看:87
本文介绍了R带条件面板和反应堆的Shiny模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对一个复杂的Shiny应用程序进行模块化,为此我有一个conditionalPanel,仅应在特定输入状态下显示.

I am trying to modularize a complex Shiny app for which I have a conditionalPanel that should only appear given a certain input state.

在我将所有模块模块化之前,input和conditionalPanel都在ui.R中,并且我可以使用类似以下的内容来引用输入:

Before I made everything modular, the input and conditionalPanel were both in ui.R, and I could reference the input using something like this:

conditionalPanel("input.select == 'Option one'", p('Option one is selected'))

现在,我已经将事情模块化了,访问输入变得更加复杂.我认为以下是实现此目的的方法,但效果不佳. (在这里,我已将内容组合到一个独立的脚本中):

Now that I have modularized things, accessing the input is more complicated. I thought the following was the way to do it, but it doesn't quite work. (Here I've combined things into a single standalone script):

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时,它才起作用:

I think this should work, but it doesn't - it only works if I make another reference to output$selected in the main ui section:

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引用本身并没有这种方式.

Unfortunately of course this has the unwanted effect of rendering the result of textOutput('selected'). I can only guess that the reason this works is because it somehow triggers the reactive in a way that the JavaScript reference alone does not.

您知道我应该如何使conditionalPanel正常工作吗?

Any idea how I should be getting this conditionalPanel to work properly?

谢谢..

结果实际上不是错误: https://github.com/rstudio/shiny /issues/1318 .请在下面查看我自己的答案.

Turns out not actually a bug: https://github.com/rstudio/shiny/issues/1318. See my own answer below.

但还请注意,实际上我比原来的conditionalPanel方法更喜欢接受的答案中给出的renderUI解决方案.

But also note that I actually like the renderUI solution given in the accepted answer better than my original conditionalPanel approach.

推荐答案

调用模块后,selectizeInput的ID为id1-select.在javaScript中,有两种访问对象属性的方法:

After calling the module the ID of selectizeInput is id1-select. In javaScript there are two ways of accessing object properties:

objectName.propertyobjectName['property']

由于ID中有-,因此我们必须通过字符串来引用它,因此第二种方法是可行的方法.

Since there is - in the ID we have to refer to it via string, so the second method is way to go.

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'.

This does work, but doesn't it violate the notion of modularity? You would have to know the code for the module internally calls that input 'select' in order to construct 'id1-select'.

是的,您是对的.

根据此文章,您使用的技巧即分配模块调用到输出$ selected,然后通过output.selected在客户端访问其值应该可以,但不能.我不知道为什么...这可能是一个错误. (我有来自github的最新闪亮版本)

According to this article, the trick you used i.e. assigning a module call to the output$selected and then accessing its value on the client side via output.selected should work but it doesn't. I don't know why...it is maybe a bug. (I have the newest shiny version from github)

我唯一想到的就是使用renderUI代替conditionalPanel,如下例所示:

The only thing I can think of is to use renderUI instead of conditionalPanel as in the example below:

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)

这篇关于R带条件面板和反应堆的Shiny模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆