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)
})