[英]Is there a way to select an entire group of choices on a pickerInput from shinyWidgets?
Here is a simple reproducible example:这是一个简单的可重现示例:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
pickerInput("test",choices=list("A"=c(1,2,3,4,5),"B"=c(6,7,8,9,10)),multiple=TRUE),
textOutput("testOutput")
)
server <- function(input, output) {
output$testOutput <- renderText({paste(input$test)})
}
shinyApp(ui = ui, server = server)
What I'd like is to click A and have the pickerInput automatically select 1,2,3,4 and 5. Or if we click B, it automatically selects 6,7,8,9, and 10.我想要的是点击A并让pickerInput自动select 1、2、3、4和5。或者如果我们点击B,它会自动选择6、7、8、9和10。
Desired output after clicking "A":单击“A”后所需的 output:
Any help is appreciated, thanks.任何帮助表示赞赏,谢谢。
You can use some JS
to get the result:您可以使用一些
JS
来获得结果:
library(shiny)
library(shinyWidgets)
js <- HTML("
$(function() {
let observer = new MutationObserver(callback);
function clickHandler(evt) {
Shiny.setInputValue('group_select', $(this).children('span').text());
}
function callback(mutations) {
for (let mutation of mutations) {
if (mutation.type === 'childList') {
$('.dropdown-header').on('click', clickHandler).css('cursor', 'pointer');
}
}
}
let options = {
childList: true,
};
observer.observe($('.inner')[0], options);
})
")
choices <- list("A" = c(1, 2, 3, 4, 5), "B" = c(6, 7, 8, 9, 10))
ui <- fluidPage(
tags$head(tags$script(js)),
pickerInput("test", choices = choices, multiple = TRUE),
textOutput("testOutput")
)
server <- function(input, output, session) {
output$testOutput <- renderText({paste(input$test)})
observeEvent(input$group_select, {
req(input$group_select)
updatePickerInput(session, "test", selected = choices[[input$group_select]])
})
}
shinyApp(ui = ui, server = server)
Idea is that you set an onClick
event for the header line, where you set an input
variable, upon which you can react in Shiny
.想法是您为 header 行设置一个
onClick
事件,您可以在其中设置一个input
变量,您可以在Shiny
中做出反应。
The whole MutationObserver
construct is a crude workaround, because I could not get a (delegated) event listener working.整个
MutationObserver
构造是一种粗略的解决方法,因为我无法让(委托的)事件侦听器工作。
What I observed is that (not bring an JavaScript
specialist):我观察到的是(不带
JavaScript
专家):
$('.dropdown-header').on()
woudl not work, because the element is not yet existing.$('.dropdown-header').on()
这样的直接事件侦听器将不起作用,因为该元素尚不存在。$(document).on('click', '.dropdown-header', ...)
did not work either.$(document).on('click', '.dropdown-header', ...)
也不起作用。 I assume that somewhere there is a stopPropagation
preventing that the event is bubbling up.stopPropagation
阻止事件冒泡。 Thus, I used the MutationObserver
to add the ('.drodown-header')
listener the moment it is created.因此,我使用
MutationObserver
在创建时添加了('.drodown-header')
侦听器。 Not the most beautiful nor a resource preserving solution, but at least a working one.不是最漂亮的解决方案,也不是资源保护解决方案,但至少是一个可行的解决方案。 Maybe, you can find out how to properly set the event listener w/o the
MutationObsever
.也许,您可以了解如何在没有
MutationObsever
的情况下正确设置事件侦听器。
If you want to keep all existing selections, you would change the observeEvent
as follows:如果您想保留所有现有的选择,您将更改
observeEvent
如下:
observeEvent(input$group_select, {
req(input$group_select)
sel <- union(input$test, choices[[input$group_select]])
updatePickerInput(session, "test", selected = sel)
})
Ok here's a shot at something for your situation using jsTreeR
.好的,这是使用
jsTreeR
针对您的情况进行的一些尝试。 The code works and does what I think you're looking for, but it's not as pretty as shinyWidgets
.该代码可以工作并且可以执行我认为您正在寻找的内容,但它不如
shinyWidgets
漂亮。 I imagine there's a way of combining this approach (largely taken from the jsTreeR example in the documentation), and the approach to create bindings in this post to create something that looks nice and has the functionality you're looking for.我想有一种方法可以结合这种方法(主要取自文档中的 jsTreeR 示例)和本文中创建绑定的方法,以创建看起来不错并具有您正在寻找的功能的东西。
library(shiny)
library(jsTreeR)
library(jsonlite)
#create nodes
nodes <- list(
list(
text="List A",
type="root",
children = list(
list(
text = "Option 1",
type = "child"
),
list(
text = "Option 2",
type = "child"
),
list(
text = "Option 3",
type = "child"
),
list(
text = "Option 4",
type = "child"
),
list(
text = "Option 5",
type = "child"
)
)
),
list(
text="List B",
type="root",
children = list(
list(
text = "Option 6",
type = "child"
),
list(
text = "Option 7",
type = "child"
),
list(
text = "Option 8",
type = "child"
),
list(
text = "Option 9",
type = "child"
),
list(
text = "Option 10",
type = "child"
)
)
)
)
types <- list(
root = list(
icon = "none"
),
child = list(
icon = "none"
)
)
#Use in shiny context - example taken from documentation for jsTreeR
ui <- fluidPage(
br(),
fluidRow(
column(width = 4,
jstreeOutput("jstree")
),
column(width = 4,
tags$fieldset(
tags$legend("Selections - JSON format"),
verbatimTextOutput("treeSelected_json")
)
),
column(width = 4,
tags$fieldset(
tags$legend("Selections - R list"),
verbatimTextOutput("treeSelected_R")
)
)
)
)
server <- function(input, output) {
output[["jstree"]] <- renderJstree(
jstree(nodes, checkboxes = TRUE, multiple=TRUE, types=types)
)
output[["treeSelected_json"]] <- renderPrint({
toJSON(input[["jstree_selected"]], pretty = TRUE, auto_unbox = TRUE)
})
output[["treeSelected_R"]] <- renderPrint({
input[["jstree_selected"]]
})
}
shinyApp(ui, server)
Note that there's no data attached to the nodes - this just gets the right UI functionality.请注意,节点上没有附加数据——这只是获得了正确的 UI 功能。 You'll have to attach values to the nodes that could then be used in downstream calculations.
您必须将值附加到可以用于下游计算的节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.