2

I am attempting to exclude a ShinyJS delay from a reactive bookmarking context in Shiny. I see that the delay ID in the URL is autogenerated and always different: delay-ad190e10123bd97f960fed7a8a9e6fde=3000.

I attempted to exclude the delay via regular expression, however I don't believe the regex is being parsed:

setBookmarkExclude(
    c("delay-[[:alnum:]]"))

I would like a way to either set the ID on the delay so it is the same every time or to regex the setBookmarkExclude to exclude the randomly generated delay ID

ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
John
  • 315
  • 1
  • 2
  • 12
  • Have a look at my answer [here](https://stackoverflow.com/a/55221062/9841389) – ismirsehregal Apr 23 '19 at 18:37
  • This is great - thank you. Is there any way to have the setBookmarkExclude execute in a different reactive context? The reason I ask is since I wrapped my setBookMarkexclude in observe, now the long (>2000) character URL is shown until the server function completes running. – John Apr 23 '19 at 20:47
  • I'm not sure what you are trying to achive. If you just want to reduce the URL length you can set the bookmarking to server-mode. I provided a simple example below. – ismirsehregal Apr 24 '19 at 08:26

1 Answers1

2

Please see the following example:

library(shiny)
library(shinyjs)

ui <- function(request) {
    fluidPage(
        useShinyjs(),
        br(),
        bookmarkButton(id="bookmarkBtn"),
        hr(),
        textOutput("ExcludedIDsOut"),
        hr(),
        sliderInput(inputId="slider", label="My value will be bookmarked", min=0, max=10, value=5),
        textOutput("out_1"),
        textOutput("out_2"),
        textOutput("out_3")
    )
}

server <- function(input, output, session) {
    
    observeEvent(input$bookmarkBtn, {
        session$doBookmark()
    })
    
    ExcludedIDs <- reactiveVal(value = NULL)
    
    observe({
        toExclude <- "bookmarkBtn"
        
        delayExclude <- grep("delay", names(input), value = TRUE)
        if(length(delayExclude) > 0){
            toExclude <- c(toExclude, delayExclude)
        }
        
        setBookmarkExclude(toExclude)
        ExcludedIDs(toExclude)
    })
    
    output$ExcludedIDsOut <- renderText({ 
        paste("ExcludedIDs:", paste(ExcludedIDs(), collapse = ", "))
    })
    
    delay(1000, {
        output$out_1 <- renderText({ 
            "My"
        })
    })
    
    delay(2000, {
        output$out_2 <- renderText({ 
            "delayed"
        })
    })
    
    delay(3000, {
        output$out_3 <- renderText({ 
            "output"
        })
    })
}

enableBookmarking(store = "url") # store = "server"
shinyApp(ui, server)

Update: Whitelist approach

library(shiny)
library(shinyjs)

ui <- function(request) {
  fluidPage(
    useShinyjs(),
    br(),
    bookmarkButton(id="bookmarkBtn"),
    hr(),
    textOutput("ExcludedIDsOut"),
    hr(),
    sliderInput(inputId="slider", label="My value will be bookmarked", min=0, max=10, value=5),
    textOutput("out_1"),
    textOutput("out_2"),
    textOutput("out_3")
  )
}

server <- function(input, output, session) {
  
  bookmarkingWhitelist <- c("slider")
  
  observeEvent(input$bookmarkBtn, {
    session$doBookmark()
  })
  
  ExcludedIDs <- reactive({
    toExclude <- setdiff(names(input), bookmarkingWhitelist)
    setBookmarkExclude(toExclude)
    toExclude
  })
  
  output$ExcludedIDsOut <- renderText({ 
    paste("ExcludedIDs:", paste(ExcludedIDs(), collapse = ", "))
  })
  
  delay(1000, {
    output$out_1 <- renderText({ 
      "My"
    })
  })
  
  delay(2000, {
    output$out_2 <- renderText({ 
      "delayed"
    })
  })
  
  delay(3000, {
    output$out_3 <- renderText({ 
      "output"
    })
  })
}

enableBookmarking(store = "url") # store = "server"
shinyApp(ui, server)

Here is a related GitHub issue, note session$getBookmarkExclude() as an alternative to keep track of the excluded inputs.

ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
  • Thank you - this answered my question. One final question if I may. I have many inputs in my app (~100) and I really only need my user to interact and manipulate about 3 in the URL. Is there a way to automatically exclude all inputs and just whitelist a few to be shown in the URL? The reason I ask is it is taking a lot of time to go through each page to determine the potential inputs to include in setBookmarkExclude(). – John Apr 24 '19 at 21:28
  • Sure, that's possible too. With this approach you dont even have to `grep` the delay IDs. I updated my answer accordingly. – ismirsehregal Apr 25 '19 at 07:02
  • 1
    One small improvement to this - it seems like `ExcludedIDs` can be made a regular `reactive()` rather than a `reactiveVal()`, which is always preferable when possible – DeanAttali Sep 25 '19 at 14:59
  • @DeanAttali thanks for the review, updated the answer accordingly. – ismirsehregal Sep 26 '19 at 05:50