This is inspired by and a follow up to Is there a way to select an entire group of choices on a pickerInput from shinyWidgets?
The selected answer works wonderfully for a single pickerInput
, but problems arise as soon as a second ("later") one is in the same app. For example, consider a setup with two pickerInput
:
library(shiny)
library(shinyWidgets)
js <- HTML("
$(function() {
let observer = new MutationObserver(callback);
function clickHandler(evt) {
Shiny.setInputValue('group_select', $(this).children('span').text(),{priority: \"event\"});
}
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), "C" = c(11,12,13,14,15))
ui <- fluidPage(
tags$head(tags$script(js)),
pickerInput("test", choices = choices, multiple = TRUE,options = list('actions-box' = TRUE)),
textOutput("testOutput"),
pickerInput("test_2", choices = choices, multiple = TRUE,options = list('actions-box' = TRUE)),
textOutput("testOutput_2")
)
server <- function(input, output, session) {
output$testOutput <- renderText({paste(input$test)})
output$testOutput_2 <- renderText({paste(input$test_2)})
observeEvent(input$group_select, {
req(input$group_select)
if(all(choices[[input$group_select]] %in% input$test_2)){
sel <- input$test_2[!(input$test_2 %in% choices[[input$group_select]])]
}else{
sel <- union(input$test_2, choices[[input$group_select]])
}
updatePickerInput(session, "test_2", selected = sel)
})
}
shinyApp(ui = ui, server = server)
With this, clicking on a group in the first pickerInput
updates the second one while clicking on a group in the second one does nothing. How do I tell the MutationObserver
to listen for and only for mutations in the second pickerInput
?
In my actual usecase, I have two different pickerInput
on two different tabs (from shinydashboard
) that I'd like to have this functionality for. So maybe it is enough to tell the MutationObserver
on which tab to look? (See How do I use shinyjs to identify if tab is active in shiny? , but being a JS beginner, I am not really sure how I can use this).
UPDATE
I've managed to get ever so slightly closer in my usecase by adding req(input$sidebar == "tab_name")
to the observeEvent
parts. Now they both update the correct pickerInput
, but for the second one, the functionality works only once after every time I've clicked on a group header in the first pickerInput
.
So, still not there. I'm trying to get a reproducible example using tabs from shinydashboard
, but for some reason as soon as I introduce them to the MWE, the whole mutationObserver
stops working altogether.
UPDATE 2
@thothal's answer worked. I rewrote the observeEvent
part to the following to get the same functionality:
observeEvent(input$group_select, {
req(input$group_select)
if(all(choices[[input$group_select[[1]]]] %in% input[[names(input$group_select)]])){
sel <- input[[names(input$group_select)]][!(input[[names(input$group_select)]] %in% my_choices[[input$group_select[[1]]]])]
}else{
sel <- union(input[[names(input$group_select)]],my_choices[[input$group_select[[1]]]])
}
updatePickerInput(session,names(input$group_select),selected = sel)
})