R Shiny modules with conditional panels and reactive

I am trying to modulate a complex Shiny application for which I have a conditionalPanel that should only appear under a certain input state.

Before I did everything modular, the input and conditional panel were both in ui.R , so I could reference the input using something like this:

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

Now that I have modular things, access to input is more complicated. I thought this was a way to do this, but it’s not quite right. (Here I combined things into a single stand-alone 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) 

I think this should work, but it doesn’t - it only works if I link 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.')) )) 

Unfortunately, of course, this has an undesirable effect for rendering the result of textOutput('selected') . I can only guess that the reason for this is that it somehow causes a reactive reaction in such a way that the JavaScript link itself is missing.

Any idea how I get this conditional panel to work correctly?

Thanks..

EDIT: the error actually fails: https://github.com/rstudio/shiny/issues/1318 . See my own answer below.

But also note that I really like the renderUI solution indicated in the accepted answer is better than my original conditionalPanel approach.

+5
source share
2 answers

After calling the module, the selectizeInput identifier is id1-select . In javaScript, there are two ways to access object properties:

objectName.property or objectName['property']

Since there is - in the ID , we must refer to it through a string, so the second way is the path.

The condition in the conditionalPanel becomes:

 input['id1-select'] == 'Option one' 

Full example:

 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) 

EDIT:

It works, but doesn't that violate the concept of modularity? You will need to know the code for the internal module that enters "select" to build "id1-select".

Yes you are right.

According to this article, the trick you used, i.e. Assigning a module call to the selected output $, and then accessing its value to the client side through output.selected should work, but this is not so. I don’t know why ... it could be a mistake. (I have the latest brilliant version from github)

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) 
+4
source

It turns out that this is actually not a mistake, just a little complicated. According to Joe Cheng ,

Right - by default we do not calculate / do not output output values ​​if they are not visible. And if we do not calculate them, you cannot use them in conditions.

You can change this behavior by setting the output for calculation each time, you can use it on your .R server (replace outputId with the appropriate value):

outputOptions(output, "outputId", suspendWhenHidden = FALSE)

So, to fix the problem with my original example, we need to add only one line to the server function:

 server <- shinyServer(function(input, output, session) { output$selected <- callModule(selector, 'id1') outputOptions(output, 'selected', suspendWhenHidden = FALSE) # Adding this line }) 
+2
source

All Articles