-
Notifications
You must be signed in to change notification settings - Fork 1
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
Enhancement (?) #81
Comments
Hi @nhward, thanks for the question and the reproducible example, I think this should work. I took a quick try and didn't figure out why it doesn't, but I'll try again this weekend. |
I have found a solution. I will first put the code that works and then go into a bit more detail afterwards. Code that works: library(shiny)
library(conductor)
guide <- Conductor$new()$
step(
title = "hello there"
)
# First module
mod_num_ui <- function(id){
ns <- NS(id)
numericInput(ns("num"), label = "Enter a number", value = 5, min = 0, max = 10)
}
mod_num_server <- function(input, output, session, global_session){
ns <- session$ns
guide$
step(
el = ns("num"), # use namespace
title = "Step 1",
text = "This is a numericInput."
)
observeEvent(
guide$isActive(session = global_session),
{
print(guide$isActive(session = global_session)) ### This never gets printed
}
)
guide$init(session = global_session)$start(session = global_session)
}
# Second module
mod_text_ui <- function(id){
ns <- NS(id)
textInput(ns("text"), label = "Type some text")
}
mod_text_server <- function(input, output, session){
ns <- session$ns
guide$
step(
el = ns("text"),
title = "Step 2",
text = "This is a textInput."
)
}
# Main app
ui <- fluidPage(
useConductor(),
mod_num_ui("num1"),
mod_text_ui("text1")
)
server <- function(input, output, session){
callModule(mod_num_server, "num1", global_session = session)
callModule(mod_text_server, "text1")
}
shinyApp(ui = ui, server = server) Explanation: When we create a guide, we assign it a unique ID, for example As you noticed, this works fine when we call it in the The solution is to pass the "main" session as an additional argument to the module. In the example above, I add an argument @nhward those explanations are maybe a bit too technical. Let me know if the code I suggested works. If you can adapt this solution to your real code, then I will add a section about this in the docs. Otherwise, feel free to ask any questions. |
Etienne, I am particularly interested in the scenario whereby the guide is created within a module, and run within the module. All your examples assume the guide is part of the global environment - hence your solution above. I am using package TidyModules to manage the modules via a module class. I highly recommend this package. This is an excellent package but its design does not easily allow me to call In modules the following pattern is normal:
By exclusively managing the guide id internally you are breaking this pattern. Specifically, step 1 cannot be achieved. Some third-party shiny-support packages (e.g. shinyjs) utilise the I hope this discussion helps create a universal solution. I reckon exposing an optional id parameter in the |
I can confirm that your fix does work. Rather than passing a global_session parameter as you suggested, I have employed the use of "Root" server code:
Module code:
The expected behavior is now working. |
Some additional comments: I noticed that methods From my experimentation:
|
That was actually quite on purpose, so that one can extract the guide (or at least part of it) from the
I thought that you could simply create a new guide there, but it seems it doesn't work while it should. Here's a (shorter) example: library(conductor)
library(shiny)
guide <- Conductor$new()$
step(
title = "hello there"
)
mod_num_ui <- function(id){
ns <- NS(id)
numericInput(ns("num"), label = "Enter a number", value = 5, min = 0, max = 10)
}
mod_num_server <- function(input, output, session){
ns <- session$ns
new_guide <- Conductor$new()$
step(
el = ns("num"),
title = "Step 1",
text = "This is a numericInput."
)
new_guide$init(session = session)
observeEvent(
new_guide$isActive(session = session),
{
print(new_guide$isActive(session = session))
}
)
new_guide$start(session = session)
}
ui <- fluidPage(
useConductor(),
mod_num_ui("num1")
)
server <- function(input, output, session){
callModule(mod_num_server, "num1")
}
shinyApp(ui = ui, server = server) I need to fix that but I think this should answer your request. Basically the problem arises when the session in which If you could share a (non-working) example of what you'd like your code to look like that would be great.
Thanks, I moved those to another issue to keep this one about your first issue only. PS: I haven't used |
Here's why the code in my previous post doesn't work: https://stackoverflow.com/a/59013515 However using |
You wrote:
This would imply that if these are both the module-session or these are both the root-session then $isActive() would work. In my testing, only when the root-sessions are used throughout, do things work correctly. My (somewhat naive) opinion is that this is because the module-sessions (somehow) translate all use of ids in the server code into namespaced ids. Since you create the The code below can be easily switched between module-session and root-session by uncommenting some code.
When I run the example app above with the module session, and inspect
When I run the example app above with the root-session, and inspect
Two things are clear:
I wonder if If the Conductor's id is also namespaced, perhaps its visibility will allow '$isActive()' to work normally in a module without resorting to root-sessions. This is pure speculation but not something I can experiment with (because the Conductor id is private) Not withstanding, there is still the issue of binding the *_is_active id to shiny in a reactive fashion. It is just possible that these issues have overlap. |
I don't think the problem is related to the name given to the id. The issue is that, as mentioned in this SO answer:
So it doesn't matter whether we I will look more into |
Etienne, I am well out of my depth to give much advice. I can see from here that This post here discusses the differences between the two calls. You wrote:
I this is not totally true. The point of my earlier comment was to show that "prebtchaioskjdqngfyvmxuzlw_is_active" was present in both the module and root session lists. I suspect the only way to reliably access the out-of-namespace ids in R is through Going by your recent code changes, the documentation would need to inform users to add
to their root-session when using modules. Perhaps programmatically warn if this is being relied upon but not set, e.g. 'Warning: session is NULL, add line "session$userData$rootSession <- session" to the main server code.' |
I can create and run guides at a module level. By this I mean I can define and init/start conductor guides within a module (provided I am careful to namespace the ids. This works great since I can manage the module and the guide together. This is excellent news!
However, the reactivity associated with the guide does not work in this mode. For example. the guide$isActive() always returns NULL because the underlying session input does not exist (not by the expected name or any other names). See REPREX.
I gather that the guide(s) must be initialised in the "main" server for the input values to be created and work correctly to give the necessary reactivity. I am not sure why this is. This limitation is not discussed in the documentation.
My questions are these: Is this behaviour by design or an oversight? Is it simple to enable the session$inputs to be created from within modules?
Below is some code I borrowed from the documentation with the initialisation and start functions triggered within the module.
The text was updated successfully, but these errors were encountered: