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