Shiny’s bookmarking
(enableBookmarking()) and shinysnap both let users return
to a saved state. This vignette helps you choose between them, use them
together, or switch an app from bookmarks to snapshot files.
| bookmarking | shinysnap | |
|---|---|---|
| where state is saved | a URL ("url") or a server directory
("server") |
a file the user downloads and uploads |
| how it restores | opens the URL in a new session | restores the current session without reloading |
| dynamic inputs | receive saved values when created, through
restoreInput() |
receive saved values when created or when they appear in the browser |
| setup | a UI function and enableBookmarking() |
no required UI changes |
| file contents | JSON encoded in a URL, or .rds files |
JSON you can read in a text editor |
| support for app changes | no migration helpers | app name and version, validate and migrate
hooks, and a restore report |
Use bookmarking when you want to send a colleague a link to what you’re looking at. Use shinysnap when you want to save your work to a file and return to it later, perhaps after the app has been updated.
You can add shinysnap to an app that already uses bookmarking:
setBookmarkExclude() are excluded
from snapshots too.setSerializer().restoreInput(), which supplies initial values to new
inputs. It restores the previous settings when the restore
finishes.The callbacks, or hooks, work similarly in both packages.
onBookmark(function(state) ...) and
snap_on_save() write to state$values.
onRestore() and snap_on_restore() read the
saved values. If you use reactiveValues,
snap_track() can save and restore them for you.
Use snap_as_bookmark_url() to turn a snapshot into a
link. The app must use enableBookmarking("url") and a UI
function to open it:
library(shinysnap)
snap <- list(
inputs = list(n = 100L, model = "complex", weights = c(0.5, 0.75)),
values = list(note = "baseline")
)
snap_as_bookmark_url(snap, base_url = "https://example.org/app/")
#> [1] "https://example.org/app/?_inputs_&n=100&model=%22complex%22&weights=%5B0.5%2C0.75%5D&_values_¬e=%22baseline%22"Inside a server function, pass session instead of
base_url to use the app’s current address. The result uses
the same _inputs_ and _values_ keys and
encoding as a URL created by session$doBookmark().
enableBookmarking() and
bookmarkButton(). Add snap_download_button()
and snap_file_input() to the UI, and
snap_download_handler() and
snap_file_restore() to the server function. The UI no
longer needs to be a function.onBookmark() hooks with
snap_on_save(), and onRestore() hooks with
snap_track() for reactiveValues (they are
written back for you) or snap_on_restore() for anything
else.setBookmarkExclude() calls; add
snap_enable(exclude = ...) patterns for ids that should
never be saved.snap_enable(),
and write a migrate hook the first time a saved value
changes meaning.shiny::testServer() tests, use
snap_as_test_inputs() to prepare the saved inputs for a
session$setInputs() call.