Shiny 如何使用动态选项为闪亮的selectizeInput添加书签?

Shiny 如何使用动态选项为闪亮的selectizeInput添加书签?,shiny,selectize.js,Shiny,Selectize.js,Shining提供了一个包装selectize.js的selectizeInput,它生成一个文本输入/组合框小部件。我想延迟加载selectizeInput的选项/值有几个原因:可能有一个很长的值列表,或者可能的值取决于其他参数。此外,我希望用户能够创建新的值(例如,选择现有值或创建自己的值) 但在所有这些情况下,selectizeInput的值都不能使用Shiny的服务器端书签进行书签。初始化selectizeInput对象时,输入中存储的书签值还不是有效的选项值 是否有人有任何聪明的解决办

Shining提供了一个包装
selectize.js
selectizeInput
,它生成一个文本输入/组合框小部件。我想延迟加载selectizeInput的选项/值有几个原因:可能有一个很长的值列表,或者可能的值取决于其他参数。此外,我希望用户能够创建新的值(例如,选择现有值或创建自己的值)

但在所有这些情况下,selectizeInput的值都不能使用Shiny的服务器端书签进行书签。初始化selectizeInput对象时,
输入中存储的书签值
还不是有效的选项值

是否有人有任何聪明的解决办法来将selectizeInput值添加到书签中

下面是处理
create
选项的最简单示例:

library(shiny)

ui <- function(request) {
  fluidPage(

    selectizeInput("foo", "Created Values Cannot Be Bookmarked", choices=c("Choose From List or Type New Value"="", "bar", "baz"),
                   options=list(create=TRUE)),
    bookmarkButton("Update URL")

  )}

server <- function(input, output) {
  onBookmarked(function(url) {
    updateQueryString(url)
  })
}

shinyApp(ui = ui, server = server, enableBookmarking = "server")
库(闪亮)

ui这里有一个解决方法,从原始问题扩展到示例。在本例中,我还显示了延迟加载

selectizeInput
的重复值存储在隐藏文本输入中。加载书签值时,隐藏的备份值用于还原真实值。要设置不在当前选项中的值,将使用shinyjs调用
selectize.js
API,以
addOption
,然后调用
addItem
。请注意,
ignoreInit=TRUE
在输入$foo observer上,以便在加载时不会覆盖隐藏的备份。另一方面,在输入$foo.bak observer上设置了
once=TRUE
,因此隐藏备份仅用于在启动时更新实际值一次。请参阅有关
observeEvent
的文档

只有当焦点集中在输入上时,才能异步加载
selectizeInput
的选项,以加速初始页面加载。带有选项的JSON文件本地存储在www/目录中

此示例还允许多个选择。选定项以逗号分隔存储在隐藏文本字段中,然后在初始化期间展开

library(shiny)
library(shinyjs)

# create JSON file with selectizeInput choices to be retrieved via ajax during load
# normally this would be run once outside of app.R
dir.create("www")
foo.choices.json <- paste('{ "cars": [\n', paste0('{ "value": "', rownames(mtcars), '", "label": "',rownames(mtcars), '" }', collapse=",\n" ), "\n]}")
writeChar(foo.choices.json, "www/foo.choices.json", eos=NULL)

# javascript to set one or more values
jsCode <- "shinyjs.setfoo = function(params){ 
  x=$('#foo')[0].selectize; 
  $.each(params.items, function(i,v) { x.addOption({value:v,label:v}); x.addItem(v) })
}"

# javascript to retrieve the choices asynchronously after focus
foo.load <- "function(query, callback) {
  if (query.length) return callback(); // not dynamic by query, just delayed load
  $.ajax({
    url: 'foo.choices.json',
    type: 'GET',
    error: function() { callback() },
    success: function(res) { callback(res.cars) }
  })
}"

ui <- function(request) {
  fluidPage(
    useShinyjs(), 
    extendShinyjs(text=jsCode),
    titlePanel("Bookmarking Created Values"),
    selectizeInput("foo", NULL, 
                   choices=c("Choose From List or Type New Value"=""),
                   multiple=TRUE,
                   options=list(create=TRUE, preload="focus", load=I(foo.load))),
    bookmarkButton("Update URL"),
    div(style="display:none", textInput("foo.bak", NULL))

  )}

server <- function(input, output, session) {
  onBookmarked(function(url) {
    updateQueryString(url)
  })
  observeEvent(input$foo, { 
    if (is.null(input$foo)) {
      updateTextInput(session, "foo.bak", value="")
    } else {
      updateTextInput(session, "foo.bak", value=input$foo)
    }
  }, ignoreInit=TRUE, ignoreNULL = FALSE)
  observeEvent(input$foo.bak, {
    js$setfoo(items=as.list(strsplit(input$foo.bak,",")[[1]]))
  }, once=TRUE)
}


shinyApp(ui = ui, server = server, enableBookmarking = "server")
库(闪亮)
图书馆(shinyjs)
#使用selectizeInput选项创建JSON文件,以便在加载期间通过ajax检索
#通常在app.R之外运行一次
创建目录(“www”)

foo.choices.json这里有一个更好的解决方案,使用服务器端对selectize的支持。支持
create=TRUE
选项的重要步骤是使用
onRestored
使用用户创建的新值更新选项

library(shiny)

init.choices <- c("Choose From List or Type New Value"="")

ui <- function(request) {
  fluidPage(
    titlePanel("Bookmarking Created Values"),
    selectizeInput("foo", NULL, 
                   choices=init.choices,
                   multiple=TRUE,
                   options=list(create=TRUE)),
    bookmarkButton("Update URL")

  )}

server <- function(input, output, session) {
  updateSelectizeInput(session, "foo", choices=c(init.choices, rownames(mtcars)), server=TRUE)
  onBookmarked(function(url) {
    updateQueryString(url)
  })
  onRestored(function(state) {
    updateSelectizeInput(session, "foo", selected=state$input$foo, choices=c(init.choices, rownames(mtcars), state$input$foo), server=TRUE)
  })
}


shinyApp(ui = ui, server = server, enableBookmarking = "server")
库(闪亮)

这真是太棒了。谢谢!超过300次的意见,没有一次投票,真是太遗憾了。小评论(可能对我自己更重要),如果书签应该在多个(连续的)会话中是有状态的,请使用
runApp()
,。。。