-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
onBookmark.Rd
209 lines (186 loc) · 6.64 KB
/
onBookmark.Rd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bookmark-state.R
\name{onBookmark}
\alias{onBookmark}
\alias{onBookmarked}
\alias{onRestore}
\alias{onRestored}
\title{Add callbacks for Shiny session bookmarking events}
\usage{
onBookmark(fun, session = getDefaultReactiveDomain())
onBookmarked(fun, session = getDefaultReactiveDomain())
onRestore(fun, session = getDefaultReactiveDomain())
onRestored(fun, session = getDefaultReactiveDomain())
}
\arguments{
\item{fun}{A callback function which takes one argument.}
\item{session}{A shiny session object.}
}
\description{
These functions are for registering callbacks on Shiny session events. They
should be called within an application's server function.
\itemize{
\item \code{onBookmark} registers a function that will be called just
before Shiny bookmarks state.
\item \code{onBookmarked} registers a function that will be called just
after Shiny bookmarks state.
\item \code{onRestore} registers a function that will be called when a
session is restored, after the server function executes, but before all
other reactives, observers and render functions are run.
\item \code{onRestored} registers a function that will be called after a
session is restored. This is similar to \code{onRestore}, but it will be
called after all reactives, observers, and render functions run, and
after results are sent to the client browser. \code{onRestored}
callbacks can be useful for sending update messages to the client
browser.
}
}
\details{
All of these functions return a function which can be called with no
arguments to cancel the registration.
The callback function that is passed to these functions should take one
argument, typically named "state" (for \code{onBookmark}, \code{onRestore},
and \code{onRestored}) or "url" (for \code{onBookmarked}).
For \code{onBookmark}, the state object has three relevant fields. The
\code{values} field is an environment which can be used to save arbitrary
values (see examples). If the state is being saved to disk (as opposed to
being encoded in a URL), the \code{dir} field contains the name of a
directory which can be used to store extra files. Finally, the state object
has an \code{input} field, which is simply the application's \code{input}
object. It can be read, but not modified.
For \code{onRestore} and \code{onRestored}, the state object is a list. This
list contains \code{input}, which is a named list of input values to restore,
\code{values}, which is an environment containing arbitrary values that were
saved in \code{onBookmark}, and \code{dir}, the name of the directory that
the state is being restored from, and which could have been used to save
extra files.
For \code{onBookmarked}, the callback function receives a string with the
bookmark URL. This callback function should be used to display UI in the
client browser with the bookmark URL. If no callback function is registered,
then Shiny will by default display a modal dialog with the bookmark URL.
}
\section{Modules}{
These callbacks may also be used in Shiny modules. When used this way, the
inputs and values will automatically be namespaced for the module, and the
callback functions registered for the module will only be able to see the
module's inputs and values.
}
\examples{
## Only run these examples in interactive sessions
if (interactive()) {
# Basic use of onBookmark and onRestore: This app saves the time in its
# arbitrary values, and restores that time when the app is restored.
ui <- function(req) {
fluidPage(
textInput("txt", "Input text"),
bookmarkButton()
)
}
server <- function(input, output) {
onBookmark(function(state) {
savedTime <- as.character(Sys.time())
cat("Last saved at", savedTime, "\n")
# state is a mutable reference object, and we can add arbitrary values to
# it.
state$values$time <- savedTime
})
onRestore(function(state) {
cat("Restoring from state bookmarked at", state$values$time, "\n")
})
}
enableBookmarking("url")
shinyApp(ui, server)
ui <- function(req) {
fluidPage(
textInput("txt", "Input text"),
bookmarkButton()
)
}
server <- function(input, output, session) {
lastUpdateTime <- NULL
observeEvent(input$txt, {
updateTextInput(session, "txt",
label = paste0("Input text (Changed ", as.character(Sys.time()), ")")
)
})
onBookmark(function(state) {
# Save content to a file
messageFile <- file.path(state$dir, "message.txt")
cat(as.character(Sys.time()), file = messageFile)
})
onRestored(function(state) {
# Read the file
messageFile <- file.path(state$dir, "message.txt")
timeText <- readChar(messageFile, 1000)
# updateTextInput must be called in onRestored, as opposed to onRestore,
# because onRestored happens after the client browser is ready.
updateTextInput(session, "txt",
label = paste0("Input text (Changed ", timeText, ")")
)
})
}
# "server" bookmarking is needed for writing to disk.
enableBookmarking("server")
shinyApp(ui, server)
# This app has a module, and both the module and the main app code have
# onBookmark and onRestore functions which write and read state$values$hash. The
# module's version of state$values$hash does not conflict with the app's version
# of state$values$hash.
#
# A basic module that captializes text.
capitalizerUI <- function(id) {
ns <- NS(id)
wellPanel(
h4("Text captializer module"),
textInput(ns("text"), "Enter text:"),
verbatimTextOutput(ns("out"))
)
}
capitalizerServer <- function(input, output, session) {
output$out <- renderText({
toupper(input$text)
})
onBookmark(function(state) {
state$values$hash <- rlang::hash(input$text)
})
onRestore(function(state) {
if (identical(rlang::hash(input$text), state$values$hash)) {
message("Module's input text matches hash ", state$values$hash)
} else {
message("Module's input text does not match hash ", state$values$hash)
}
})
}
# Main app code
ui <- function(request) {
fluidPage(
sidebarLayout(
sidebarPanel(
capitalizerUI("tc"),
textInput("text", "Enter text (not in module):"),
bookmarkButton()
),
mainPanel()
)
)
}
server <- function(input, output, session) {
callModule(capitalizerServer, "tc")
onBookmark(function(state) {
state$values$hash <- rlang::hash(input$text)
})
onRestore(function(state) {
if (identical(rlang::hash(input$text), state$values$hash)) {
message("App's input text matches hash ", state$values$hash)
} else {
message("App's input text does not match hash ", state$values$hash)
}
})
}
enableBookmarking(store = "url")
shinyApp(ui, server)
}
}
\seealso{
enableBookmarking for general information on bookmarking.
}