# Chapter 11 Bookmarking

This chapter is in development...

### Exercise 11.3.1

Generate app for visualising the results of noise::ambient_simplex(). Your app should allow the user to control the frequency, fractal, lacunarity, and gain, and be bookmarkable. How can you ensure the image looks exactly the same when reloaded from the bookmark? (Think about what the seed argument implies).

#### Solution

For this example, we’ll use the bookmarking by setting `enableBookmarking = "url"` within the `shinyApp` function. In order to ensure the simulation is the same each time we re-render the bookmark we’ll create a grid to use for points then set the seed to `42` to ensure the same image is rendered when the bookmark is loaded.

``````library(shiny)
library(ambient)

ui <- fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("frequency", "Frequency", min = 0, max = 1, value = 0.01),
selectInput("fractal", "Fractal", choices = c("none", "fbm", "billow", "rigid-multi")),
sliderInput("gain", "Gain", min = 0, max = 1, value = 0.5),
),
mainPanel(
plotOutput("result")
)
)
)

server <- function(input, output, session) {

grid <- long_grid(seq(1, 10, length.out = 1000), seq(1, 10, length.out = 1000))

noise <- reactive({
ambient::gen_simplex(
x = grid\$x,
y = grid\$y,
seed = 42,
frequency = input\$frequency,
fractal = input\$fractal,
gain = input\$gain
)
})

output\$result <- renderPlot({
plot(grid, noise())
})

observe({
reactiveValuesToList(input)
session\$doBookmark()
})
onBookmarked(updateQueryString)
}

shinyApp(ui = ui, server = server, enableBookmarking = "url")``````

### Exercise 11.3.2

Make a simple app that lets you upload a csv file and then bookmark it. Upload a few files and then look in shiny_bookmarks. How do the files correspond to the bookmarks? (Hint: you can use readRDS() to look inside the cache files that Shiny is generating).

#### Solution

By setting the `state\$values\$data` equal to the `data` reactive, we can store the contents of the uploaded `csv`. Looking in the `shiny_bookmarks` folder we see an `input.rds` which has the same 4 arguments as `input\$file`:

1. `name`
2. `size`
3. `type`
4. `datapath`

All of these except the `datapath` are the same as when we upload the file; rather than the temporary location the file is saved to within the shiny session, the datapath becomes `0.csv`, a csv file created within the same folder are our `input.RDS`.

``````library(shiny)

ui <- function(request){
fluidPage(
sidebarLayout(
sidebarPanel(
bookmarkButton(),
fileInput("file", "Choose CSV File", multiple = TRUE,accept = ".csv")
),
mainPanel(
tableOutput("contents")
)
)
)
}

server <- function(input, output) {

# create reactive of input file
data <- reactive({
req(input\$file)
})

# set the state to the df reactive
onBookmark(function(state){
state\$values\$data <- data()
})

# on restore set df to the state
onRestore(function(state){
data <- reactive(state\$values\$data)
})
enableBookmarking(store="server")
}

shinyApp(ui, server)``````