简体   繁体   English

有没有办法 select 来自shinyWidgets 的pickerInput 上的一整组选择?

[英]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)

Explanation解释

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专家):

  • The content of the dropdown is not generated before the first click.下拉菜单的内容在第一次点击之前不会生成。 Hence, a direct event listener like $('.dropdown-header').on() woudl not work, because the element is not yet existing.因此,像$('.dropdown-header').on()这样的直接事件侦听器将不起作用,因为该元素尚不存在。
  • Event delegation a la $(document).on('click', '.dropdown-header', ...) did not work either.事件委托 a la $(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的情况下正确设置事件侦听器。


Update更新

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.

相关问题 (AD) 使用 shinywidgets 从 pickerInput 中删除“全选”操作按钮 - (AD) Remove "Select All" action button from pickerInput using shinywidgets 你能告诉 MutationObserver 只听特定的输入,例如 select 选择器输入中的一整组选择吗? - Can you tell a MutationObserver to only listen to specific inputs, e.g. to select an entire group of choices in a pickerInput? pickerInput默认选择所有选项 - pickerInput default select all choices R ShinyWidgets pickerInput:全选时如何不过滤数据框 - R shinyWidgets pickerInput: how to not filter data frame when select all 是否有可能使用尚未在ShinyWidgets的功能pickerInput中作为“选择”上传的数据框列的唯一值? - Is it possible to use the unique values of a dataframe column that is yet to upload as 'choices' in the function pickerInput of shinyWidgets? 如何确保在 pickerInput 选项中每个组中至少选择一个项目 - How to ensure that in pickerInput choices at least one item is selected in each group 在 renderUI 中使用时,shinyWidgets::pickerInput 不出现 - shinyWidgets::pickerInput not appearing when using within renderUI 将国家标志添加到选择器输入的闪亮小部件。 - Adding country flag to pickerinput shinywidgets. 如何更改shinyWidgets package的pickerInput的字体大小 - how to change font size for pickerInput of shinyWidgets package pickerInput 未清除所有选项 - pickerInput Not Clearing All Choices
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM