onBookmark: Add callbacks for Shiny session bookmarking events

Description Usage Arguments Details Modules See Also Examples

View source: R/bookmark-state.R

Description

These functions are for registering callbacks on Shiny session events. They should be called within an application's server function.

Usage

1
2
3
4
5
6
7

Arguments

fun

A callback function which takes one argument.

session

A shiny session object.

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 onBookmark, onRestore, and onRestored) or "url" (for onBookmarked).

For onBookmark, the state object has three relevant fields. The 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 dir field contains the name of a directory which can be used to store extra files. Finally, the state object has an input field, which is simply the application's input object. It can be read, but not modified.

For onRestore and onRestored, the state object is a list. This list contains input, which is a named list of input values to restore, values, which is an environment containing arbitrary values that were saved in onBookmark, and dir, the name of the directory that the state is being restored from, and which could have been used to save extra files.

For 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.

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.

See Also

enableBookmarking for general information on bookmarking.

Examples

  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
## 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 <- digest::digest(input$text, "md5")
  })
  onRestore(function(state) {
    if (identical(digest::digest(input$text, "md5"), 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 <- digest::digest(input$text, "md5")
  })
  onRestore(function(state) {
    if (identical(digest::digest(input$text, "md5"), 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)
}

tomkuipers1402/shiny documentation built on Feb. 13, 2020, 7:22 p.m.