Shiny: Modules and conditional panels

Created on 15 Feb 2017  Â·  16Comments  Â·  Source: rstudio/shiny

(Edited: there's really only one bug and the original post was misleading)

It's impossible to do the following (which I think is how everyone would go about using modules + conditional panels):

conditionalPanel(
 condition = paste0("input.", ns("smooth"), " == true"),
 ...
)

since the namespacing that ns provides for modules includes a dash (i.e. moduleID-elementID), JS gets mad, and we need to at least do a good job of documenting that, since there's no expectation that users should know the internals of how namespacing works (but in this case, this obviously becomes relevant). When the condition of a conditionalPanel involves an input or output coming from a module, you need to do this (use brackets instead of a dot):

conditionalPanel(
 condition = paste0("input['", ns("smooth"), "'] == true"),
 ...
)

Which is not really ideal... But unless we want to change the internals of NS (which I don't think we do), we need to document this. I'd suggest doing it in the three places that people are probably going to check if they get in trouble:

  • documentation for conditional panel
  • article for dynamic UI (section on conditional panel)
  • article for modules (just a note)

Most helpful comment

It just occurred to me, we could fix this by making the conditionalPanel itself namespace-aware. It's probably too late to do this by default? But:

conditionalPanel("input.viewVerbose", ns = ns, ...)

And conditionalPanel would add an attribute to its HTML element that indicates what namespace to use to populate input/output.

All 16 comments

cc @yonicd

Here's a small example:

library(shiny)

condpanelUI <- function(id) {
  ns <- NS(id)

  tagList(
    checkboxInput(ns("checkbox"), "Make panel visible"),
    conditionalPanel(paste0("input.", ns("checkbox")), "This is the conditional panel")
  )
}

ui <- fluidPage(
  condpanelUI("foo")
)

server <- function(input, output, session) {
}

shinyApp(ui, server)

The error message in Chrome's JS console is:

VM160:2 Uncaught ReferenceError: checkbox is not defined
    at Object.eval (eval at scopeExprToFunc (utils.js:167), <anonymous>:2:32)
    at utils.js:169
    at ShinyApp.$updateConditionals (shinyapp.js:410)
    at ShinyApp.dispatchMessage (shinyapp.js:507)
    at WebSocket.c.onmessage (shinyapp.js:112)

And the value of expr right before the error is "input.foo-checkbox".

image

If the code is changed from:

paste0("input.", ns("checkbox"))

to:

paste0("input['", ns("checkbox"), "']")

it works.

that's what i have now (and it doesnt work for me) is there a new shiny version since this thread was opened?

> packageVersion('shiny')
[1] ‘1.0.3’
aesColourContNS=function(type,session) {
  ns<-session$ns
  id=gsub("-a", "", ns("a"))
  iId=paste0('pop',toupper(type),'fixedPal')
  fP=ns(paste0('pop',toupper(type),'fixedPal'))
  #column(width=2,
  shiny::div(
  shiny::selectizeInput(inputId = fP,
                 label='Pallete',
                 choices = c('Manual','Blues', 'BuGn', 'BuPu', 'GnBu', 'Greens', 'Greys', 'Oranges', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'Purples', 'RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd'),
                 selected = 'Blues'),

  shiny::conditionalPanel(paste0("input['", id, "-", iId ,"'] == Manual"),
    lapply(c('Low','High'),function(x,type){
    if(x=='Low'){
      pad='padding:0px 0px 0px 10px;'
      init.col='red'
    } 
    if(x=='High'){
      pad='padding:0px 10px 0px 0px;'
      init.col='blue'
    } 

      shiny::column(width=6, style=pad,
           do.call(colourpicker::colourInput,
                   args=list(inputId = ns(paste0('pop',toupper(type),x)),
                             label = x,
                             value =  init.col,
                             returnName = F,
                             showColour = "background")
                  )
           )
  },type)
  )
  )
}

It just occurred to me, we could fix this by making the conditionalPanel itself namespace-aware. It's probably too late to do this by default? But:

conditionalPanel("input.viewVerbose", ns = ns, ...)

And conditionalPanel would add an attribute to its HTML element that indicates what namespace to use to populate input/output.

Huh, that would actually work extremely well I think.

joe is also answering me here simultaneously. did a pull for his patch, still not responding to the change in syntax

https://github.com/metrumresearchgroup/ggedit/pull/18

On Fri, Jun 2, 2017 at 11:57 AM, Winston Chang notifications@github.com
wrote:

@yonicd https://github.com/yonicd You need to change it here:
https://github.com/metrumresearchgroup/ggedit/
blob/ffc1a35/R/ggeditUI.R#L20

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rstudio/shiny/issues/1586#issuecomment-305830959, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABrJX5mL5-iVuMS8eRck8_OgYk6JvCy1ks5sADEBgaJpZM4MB2EN
.

--
Yoni

You do not learn to swim from books and lectures on the theory of buoyancy
(Box 1990)

Here's a minimal example, with a plot added:

library(shiny)

condpanelUI <- function(id) {
  ns <- NS(id)

  tagList(
    checkboxInput(ns("checkbox"), "Make panel visible"),
    conditionalPanel(
      # paste0("input['", ns("checkbox"), "']"),   # Fixed version
      paste0("input.", ns("checkbox")),
      "This text should show only when checkbox is checked."
    )
  )
}

ui <- fluidPage(
  condpanelUI("foo"),
  plotOutput("plot")
)

server <- function(input, output, session) {
  output$plot <- renderPlot({
    plot(1:5, 1:5)
  })
}

shinyApp(ui, server)

When deployed to shinyapps.io, the conditionalPanel doesn't work, and the plot doesn't display. However, if the condition is fixed (by commenting out the condition and uncommenting the other version), the plot displays fine. In the screenshot, on the left is the broken version, on the right is the fixed version, both deployed to shinyapps.io:

image

Interestingly, if the broken version is deployed to RSC, the plot still shows. I believe this is due to some different error handling on RSC. On the left, I've deployed the broken version to shinyapps.io. On the right, I deployed the broken version to RSC. Note the differences in the stack trace.

image

These apps are deployed to:

@alandipert If your plate isn't too full--it'd be great if we could take a look at this together next week (either you and I, or you and Winston). The fix is straightforward, but I think it'd be a good chance to introduce you to the ins and outs of modules and especially why we made some of the design decisions we did--I'm sure you will have a lot of "Why didn't you just..." questions as we go through it.

@jcheng5 and I looked at the difference between shinyapps.io and RSC, and the different behavior is due to different transports on the two platforms. RSC uses websockets, whereas shinyapps.io uses an emulation layer via sockjs.

On RSC, the messages from the server are processed individually, and a JS exception will stop the processing of just that message.

On shinyapps.io, the messages from the server can be batched up and sent all at once, and a JS exception will stop the processing of all messages that were batched.

In my example, the JS error happens while processing one of the earlier messages, and the plot is included in a later message. When the messages are not batched (as on RSC), the JS error doesn't affect the plot. When the messages are batched (as on shinyapps.io) the error causes the plot not to render.

On RSC, it's possible to use the sockjs emulation by pressing ctrl-alt-shift-A and unchecking "websocket", then reloading the app. If you do that, then it will behave like shinyapps.io: the plot won't show. (On shinyapps.io, pressing the key combo will also bring up the websocket option, but even though it can be checked and unchecked, it actually has no effect -- it never uses websockets.)

@yonicd Are you seeing any errors in your JS console? If so, those errors are probably preventing the plots from displaying.

screen shot 2017-06-02 at 12 54 47

I mean that the JS errors will probably prevent the plots from displaying when you deploy your app on Shiny Server Pro or shinyapps.io.

got it to work after seeing the js error. i had to force the rhs of the logical to be a string on the R side.

which was a typo on my part.

https://github.com/metrumresearchgroup/ggedit/commit/feaf6b183100b3a17ad818141035c9ccc78e0491

thanks!

Closed by #1735.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

howardcoleman picture howardcoleman  Â·  5Comments

hlherrera picture hlherrera  Â·  5Comments

wch picture wch  Â·  3Comments

hudon picture hudon  Â·  4Comments

daattali picture daattali  Â·  5Comments