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

Adding a state list to avoid update...Input #1

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

vnijs
Copy link

@vnijs vnijs commented Feb 14, 2015

@jcheng5 I made changes changes to shiny-resume. From renderUI you can use r_state to save and restore inputs after refresh. I also set the SSUID to stay the same on refresh. I could also add saving and loading state options. I'm not sure, however, about the best way to remove older sessions from memory. I'm curious to hear your comments.

I assume this functionality would be useful for other also. Not sure how to package it up efficiently though. For example, when I have tried to put the functions in state.R into the R/ directory and export them they are (1) either not found or (2) the functions can't find r_state. Would you have put the shiny state into the function call? See related SO question linked below.

http://stackoverflow.com/questions/28147302/access-shiny-environment-from-exported-functions

@vnijs
Copy link
Author

vnijs commented Feb 14, 2015

@jcheng5 I put shiny-resume on my server [EDIT -- not working on non-pro version of shiny-server]. You should see my message and settings.

I also put it on shinyapp.io but on each refresh "_w_e8455651" is added to the url although it doesn't affect state shown:

https://mostly-harmless.shinyapps.io/shiny-resume/_w_e8455651/_w_e8455651/_w_e8455651/?
SSUID=55c6ebf3279231682632e1d2dc514df5

@vnijs
Copy link
Author

vnijs commented Feb 14, 2015

@jcheng5 The approach works fine locally. It also works with shiny-server pro (e.g., shinyapps.io) although it keeps adding components to the url. However, it doesn't seem to work well with the non-pro version of shiny-server. Try it out at the link below. After a few refreshes it locks up (see attached screen shot of the js console).

http://vnijs.rady.ucsd.edu:3838/shiny-resume/

screen shot 2015-02-14 at 12 58 33 pm

@jcheng5
Copy link
Owner

jcheng5 commented Feb 15, 2015

Hi Vincent, I'm on vacation but will try to take a look when I'm back mid week--feel free to bump this thread if you don't hear from me by Thursday.

@vnijs
Copy link
Author

vnijs commented Feb 15, 2015

Thanks for the update Joe. Enjoy your vacation!

@vnijs
Copy link
Author

vnijs commented Feb 18, 2015

In a multi-page app a refresh would always take me back to the 'home' page. Or if you send the link with session information to a collaborator/student they would not go to the page you were working on. Could the shiny-resume approach be combined with a (simple) url dispatcher where something like the url below would take you to, for example, the Data > View tab in a shiny app?

https://mostly-harmless.shinyapps.io/shiny-resume/?data/view/SSUID=79859a55afd3d30fa91425e8b3a67a1e

Sort of like in django (see link below) where regular expression are used to parse the url but then linked to updateTabsetPanel for Shiny

https://docs.djangoproject.com/en/1.7/topics/http/urls/

I was reminded of this when I saw:

http://www.sonnyjs.org/demo/?public/register

@vnijs
Copy link
Author

vnijs commented Feb 20, 2015

as suggested ... bump

@jcheng5
Copy link
Owner

jcheng5 commented Feb 22, 2015

I'll take a look at this tomorrow.

@jcheng5
Copy link
Owner

jcheng5 commented Feb 23, 2015

OK, a couple of points.

  • My original example was just to show that you could have save and restore callbacks. What you actually choose to save/restore in those cases is totally up to you.
    • If you want to store r_state/r_data, those can just be made part of the save reactive--no reason that I can see to have those be explicitly represented in the manage_session parameter list. (In other words, the save reactive expression could return list(r_state=r_state, r_data=r_data))
    • Regarding your multi-page app scenarios, if you want save to store your "location" within the app and have restore put you back there, you should be able to do that without needing to change the implementation of session.R.
  • You changed the SSUID to be preserved, whereas I generated new ones on every session. The problem with preserving them, is if I email a link with SSUID to two people, and one of them starts clicking around on it, then it changes it for the second person. If your intention for this functionality is just to resume sessions and not to make bookmarkable links, then that side-effect might be fine--maybe that should be an option.
  • I support your desire to not want to write update*Input for each input value that you save--however, I would want any solution to be general across both renderUI-based controls and less dynamic UI. This is really the sticking point that has held us up from tackling this functionality in earnest in Shiny itself; I haven't had time to think seriously about it and the solutions others have come up with have all been fraught with limitations.

@vnijs
Copy link
Author

vnijs commented Feb 24, 2015

Thanks for your comments Joe. I agree that sending a link with session id would allow people to make changes before everyone has had a chance to see what was there. However, if I really wanted multiple people to see the exact state I am looking at now I could send them a state file they can restore.

With the current approach you would need update* for anything in ui.R but it still reads from the saved state and that is fine for me. You could source the state_... functions in ui.R I guess but they would not 'see' the state containers unless they are in the global environment. Not sure how to work around that.

Your requirements are of course much more general than mine. I really want to integrate this setup in my app but the problem is that on shiny-server it adds text to the url on each refresh (i.e., "_w_841382cc/"). As I mentioned ... "The approach works fine locally. It also works with shiny-server pro (e.g., shinyapps.io) although it keeps adding components to the url. However, it doesn't seem to work well with the non-pro version of shiny-server. ... After a few refreshes it locks up (see attached screen shot of the js console)."

For url dispatching, what do you think about a simplified version of the approach shown here ? I would only include the id for the navbar menu and the tab in the url.

@jcheng5
Copy link
Owner

jcheng5 commented Feb 25, 2015

I've committed a fix to www/session.js that fixes the excessive _w_841382cc. However, I wasn't able to repro the lock up you saw. I did see the error message one time but it didn't seem to affect the operation of the app. Are you still seeing it lock up?

I read the "Shiny saving URL state subpages and tabs" stackoverflow post a couple of times. I don't think the url_handler.js is necessary; I believe that setNavbar and setTab are covered with updateTabsetPanel(..., value=tabname).

I suspect it may be tricky to make this approach work if the tabset in question is created by renderUI (as the updateTabsetPanel may be called before the tab exists). I have some vague, complicated ideas of how we might tackle this in the general case. But for your specific case, if the tabset is created by renderUI then just set the default tab when you're rendering it.

@vnijs
Copy link
Author

vnijs commented Feb 25, 2015

Thanks for the fix Joe. The app locked up once but seems to work fine overall.

I agree that updateTabsetPanel should work. I would still need something like setUrl to keep the url updated if I change tabs right?

To deal with tabsets created by (nested) renderUI a two-set approach seems to work when I tried it by linking to a button/icon:

updateTabsetPanel(session, "nav_radiant", selected = "Data")
updateTabsetPanel(session, "datatabs", selected = "View")

Question: I haven't used addCustomMessageHandler before. How do you test your code? The most convenient way would be pasting to the js console but that gives "ReferenceError: data is not defined"

@vnijs
Copy link
Author

vnijs commented Mar 5, 2015

Is this perhaps the issue your were refering to with updateTabsetPanel?

rstudio/shiny#595 (comment)

@vnijs
Copy link
Author

vnijs commented Apr 3, 2015

@jcheng5 Just an FYI that I got resume with session.js working in radiant. See the Data > Visualize tab for a graph loaded from a state-file. This session will be deleted within 7 days. I did have some difficulty loading state-files so I ended up using session$onSessionEnded to write to sessionStore. Thanks again for your input!!

I haven't figure out how to setup site-navigation with updateTabsetPanel yet. I got stuck on this issue. If you have any comments/suggestions please let do me know.

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

Successfully merging this pull request may close these issues.

None yet

2 participants