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

Setting session$userData on the parent session from within a module #1546

Closed
daattali opened this issue Jan 18, 2017 · 11 comments
Closed

Setting session$userData on the parent session from within a module #1546

daattali opened this issue Jan 18, 2017 · 11 comments
Assignees

Comments

@daattali
Copy link
Contributor

daattali commented Jan 18, 2017

Related to #1512

I want to add a flag to the session so that I know if this is the first time or not that a function gets called. I do this using the new session$userData env. When modules are not involved, this is fine.

If the function happens to be called from inside a module, which means the session object will be a proxy session, I want to be able to grab the parent session object so that I can attach the flag to it instead. I saw that a proxy session has a $parent() , but it seems to be returning NULL to me.

@bborgesr
Copy link
Contributor

You can always pass in the real session as an argument to the module, but I understand that may be clutter for you.

This works (the reason $ didn't work is because we've explicitly disallowed it, so you wouldn't be able to do things like session$myVar <- ...):

library(shiny)

modUI <- function(id) {}
mod <- function(input, output, session) {
  parentSession <- .subset2(session, "parent")
  parentSession$userData$flag <- TRUE
}

ui <- fixedPage(
  modUI("modID")
)

server <- function(input, output, session) {
  callModule(mod, "modID")
  print(session$userData$flag)
}

shinyApp(ui, server)

We can't guarantee that this won't change (although that's unlikely)... Given that this is a reasonable thing that an app author may need to do, I think we'll probably add direct support (and documentation) for this at some point.

I hope this workaround does the job for now!

@daattali
Copy link
Contributor Author

Cool, I didn't think of trying session[['parent']] instead of $. Is parent purposely returning NULL because you don't want people to use it, because it violated the isolation of the module?

I won't be using this because I want to use it in a package so I prefer not to use something without an explicit API, but it's useful to know, thanks

@bborgesr
Copy link
Contributor

Yeah, we don't want people to use it, but not because it violates the isolation of the module.

Rather, everything in session (both with or without modules) is supposed to be read-only, with the exception of elements inside session$userData (note that the environment session$userData itself should also be read-only). So the reason that both $ and [[ were purposely returning NULL is so that you can't write into the parent's session environment. However, you should be able to write an object (or mutate it) into the parent's session$userData environment. That's what we'll probably add an API for in the future.

@daattali daattali changed the title How to get a reference to the parent session of a session_proxy? Setting session$userData on the parent session from within a module Jan 18, 2017
@daattali
Copy link
Contributor Author

Makes sense, thanks for the answer. I'll leave this issue open in case you want it as a tracker for adding the API you talked about. You can close the issue if you want

@ppagnone
Copy link

Hi, how are you?
I have a code that get data with information associated to each user that entered to app. I am using session$userData to save that information for each session of user.

@bborgesr I saw your comment about read-only. Do you say that is not recommendable to save data in session$user or I understand bad?

Thanks in advance

@bborgesr
Copy link
Contributor

@ppagnone: You can save data into session$userData. That is exactly what I did in the app above (for modules, which is actually more complicated than for a non-modular app directly). This is the correct usage of session$userData. From the documentation:

userData An environment for app authors and module/package authors to store whatever session-specific data they want.

What you can't do is actually overwrite the userData environment itself, or add/change any direct children of session.

So, this is okay/good:

session$userData$flag <- TRUE

But this is not:

session$userData <- TRUE

Same problem here:

session$flag <- TRUE

That was not Dean's question. His question was, when using modules, how to store data in the userData environment of the parent session.

So, by all means, do save whatever variables you want inside session$userData, just don't save anything into session directly.

@ppagnone
Copy link

@bborgesr Thank you! you were very understandable. Excuse me my misunderstanding.

@bborgesr
Copy link
Contributor

A semi-related question: how to set suspendWhenHidden = FALSE to all outputs of a module, from the parent app? From here: https://groups.google.com/forum/#!topic/shiny-discuss/F-EwQGELS1c

@fabiangehring
Copy link

fabiangehring commented May 11, 2017

+1 to allow session$userData$whatever <- TRUE (without "parent-workaround")

@jcheng5
Copy link
Member

jcheng5 commented May 11, 2017

I think there might have been some wrong information in this thread. The session$userData in a module (any module) and the session$userData in the top-level server function, are always the same environment.

@jcheng5 jcheng5 closed this as completed May 11, 2017
@bborgesr
Copy link
Contributor

bborgesr commented Jun 6, 2017

@jcheng5 I think this should be re-opened. You are right and thanks for the clarification. And sorry for spreading confusion! This really makes a lot of sense.

But, fundamentally, the original and remaining problem is that you cannot write into the session$userData environment from within a module.

I.e. you should be able to do this:

library(shiny)

modUI <- function(id) {}
mod <- function(input, output, session) {
  session$userData$flag <- TRUE
}

ui <- fixedPage(
  modUI("modID")
)

server <- function(input, output, session) {
  callModule(mod, "modID")
  print(session$userData$flag)
}

shinyApp(ui, server)

But you have to do this instead:

library(shiny)

modUI <- function(id) {}
mod <- function(input, output, session) {
  parentSession <- .subset2(session, "parent")
  parentSession$userData$flag <- TRUE
}

ui <- fixedPage(
  modUI("modID")
)

server <- function(input, output, session) {
  callModule(mod, "modID")
  print(session$userData$flag)
}

shinyApp(ui, server)

@bborgesr bborgesr reopened this Jun 6, 2017
@bborgesr bborgesr self-assigned this Jun 7, 2017
@bborgesr bborgesr added the review label Jun 7, 2017
@jcheng5 jcheng5 closed this as completed in 3841f22 Jun 8, 2017
jcheng5 added a commit that referenced this issue Jun 8, 2017
Fixed #1546: make it possible to write into a module's session$userData non-hackily
@jcheng5 jcheng5 removed the review label Jun 8, 2017
dmpe added a commit to dmpe/shiny that referenced this issue Jun 9, 2017
…itrary data into a module's session$userData

More descriptive NEWS item and added an explanatory comment to the code
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