Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modules and conditional panels #1586

Closed
bborgesr opened this issue Feb 15, 2017 · 17 comments
Closed

Modules and conditional panels #1586

bborgesr opened this issue Feb 15, 2017 · 17 comments

Comments

@bborgesr
Copy link
Contributor

bborgesr commented Feb 15, 2017

(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)
@bborgesr
Copy link
Contributor Author

cc @yonicd

@wch
Copy link
Collaborator

wch commented Jun 2, 2017

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.

@yonicd
Copy link

yonicd commented Jun 2, 2017

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)
  )
  )
}

@wch
Copy link
Collaborator

wch commented Jun 2, 2017

@jcheng5
Copy link
Member

jcheng5 commented Jun 2, 2017

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.

@jcheng5
Copy link
Member

jcheng5 commented Jun 2, 2017

Huh, that would actually work extremely well I think.

@yonicd
Copy link

yonicd commented Jun 2, 2017 via email

@wch
Copy link
Collaborator

wch commented Jun 2, 2017

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:

@jcheng5
Copy link
Member

jcheng5 commented Jun 2, 2017

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

@wch
Copy link
Collaborator

wch commented Jun 2, 2017

@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.)

@wch
Copy link
Collaborator

wch commented Jun 2, 2017

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

@yonicd
Copy link

yonicd commented Jun 2, 2017

screen shot 2017-06-02 at 12 54 47

@wch
Copy link
Collaborator

wch commented Jun 2, 2017

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.

@yonicd
Copy link

yonicd commented Jun 2, 2017

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.

yonicd/ggedit@feaf6b1

@yonicd
Copy link

yonicd commented Jun 2, 2017

thanks!

@wch
Copy link
Collaborator

wch commented Aug 8, 2017

Closed by #1735.

@wch wch closed this as completed Aug 8, 2017
schyen pushed a commit to OxfordCMS/OCMSlooksy that referenced this issue Jan 15, 2020
@kieran-mace
Copy link

Hey team, thank you very much for making this update. But can you please provide documentation on how to use the ns argument within the condition?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants