问题
I have the shiny app below in which I pass the values of a list with characters inside a selectImput()
but while all those values seem to be selected (and they should be) by checking their count in the third column the selectize inputs seem to be empty. I think that for this issue is responsible the list words
I created.
library(shiny)
library(DT)
library(jsonlite)
selector <- function(id, values, items = values){
options <- HTML(paste0(mapply(
function(value, item){
as.character(tags$option(value = value, item))
}, c("", values), c("", items)
), collapse = ""))
as.character(
tags$select(
id = id, class = "form-control", multiple = "multiple", options
)
)
}
name<-c("Jack","Bob","Jack","Bob")
item<-c("apple","olive","banana","tomato")
d<-data.frame(name,item,stringsAsFactors = FALSE)
words<-tapply(d$item, d$name, I)
nrows <- length(words)
js <- c(
"function(settings) {",
sprintf("var nrows = %d;", nrows),
sprintf("var words = %s;", toJSON(words)),
" var table = this.api().table();",
" function selectize(i) {",
" $('#slct' + i).selectize({",
" items: words[i-1],",
" onChange: function(value) {",
" table.cell(i-1, 2).data(value.length);",
" }",
" });",
" }",
" for(var i = 1; i <= nrows; i++) {",
" selectize(i);",
" Shiny.setInputValue('slct' + i, words[i-1]);",
" }",
"}"
)
ui <- fluidPage(
br(),
DTOutput("table"),
div( # this is a hidden selectize input whose role is to make
# available 'selectize.js'
style = "display: none;",
selectInput("id", "label", c("x", "y"))
)
)
server <- function(input, output, session) {
output[["table"]] <- renderDT({
dat <- data.frame(
FOO = c(unique(d$name)),
Words = vapply(
1:nrows,
function(i){
selector(paste0("slct", i), words[[i]])
},
character(1)
),
Count = lengths(words),
stringsAsFactors = FALSE
)
datatable(
data = dat,
selection = "none",
escape = FALSE,
rownames = FALSE,
options = list(
initComplete = JS(js),
preDrawCallback = JS(
'function() { Shiny.unbindAll(this.api().table().node()); }'
),
drawCallback = JS(
'function() { Shiny.bindAll(this.api().table().node()); }'
)
)
)
}, server = FALSE)
}
shinyApp(ui, server)
回答1:
The words
list is named:
> name <- c("Jack","Bob","Jack","Bob")
> item <- c("apple","olive","banana","tomato")
> d <- data.frame(name, item)
>
> ( words <- tapply(d$item, d$name, I) )
$Bob
[1] olive tomato
Levels: apple banana olive tomato
$Jack
[1] apple banana
Levels: apple banana olive tomato
Therefore its JSON representation is:
> toJSON(words)
{"Bob":["olive","tomato"],"Jack":["apple","banana"]}
This is not an array. Remove the names and you get the wanted array of arrays:
> toJSON(unname(words))
[["olive","tomato"],["apple","banana"]]
Or instead of using 'jsonlite', use a basic JSON stringifier:
sprintf("[%s]", toString(vapply(words, function(x){
sprintf("[%s]", toString(shQuote(x)))
}, character(1))))
# "[['olive', 'tomato'], ['apple', 'banana']]"
来源:https://stackoverflow.com/questions/65668902/datatable-displays-empy-selectinput-while-values-are-selected-by-default