user2767152
user2767152

Reputation: 55

shiny checkboxgroupinput dynamic background color control

I am designing a fully dynamic UI for the purpose of demonstration with shiny. There are a few steps on my list, I am working on one after another.

  1. make the customize the background colors of the multi-choice boxes generated by the function 'checkboxGroupInput'
  2. make the checkboxes more dynamic -- when the background color will be on/off when select/de-select one checkbox

I got the solution in another post, and it works perfectly. (how to make the checkboxgroupinput color-coded in Shiny) Here is the code I got:

my_checkboxGroupInput <- function(variable, label, choices, selected, colors){
  choices_names <- choices
  if(length(names(choices))>0) my_names <- names(choices)
  div(id=variable,class="form-group shiny-input-checkboxgroup shiny-input-container shiny-bound-input",
    HTML(paste0('<label class="control-label" for="',variable,'">',label,'</label>')),
    div( class="shiny-options-group",
      HTML(paste0('<div class="checkbox" style="color:', colors,'">',
                    '<label>',
                    '<input type="checkbox" name="', variable, 
                        '" value="', choices, 
                        '"', ifelse(choices %in% selected, 'checked="checked"', ''), 
                    '/>',
                    '<span>', choices_names,'</span>',
                    '</label>',
                  '</div>', collapse = " "))
      )
    )
}

library(shiny)
my_names <- c('one'=1,'two'=2,'three'=3)
my_selected <- c(1,2)
my_colors <-c('blue','red','green')
shinyApp(
  ui=fluidPage(uiOutput("my_cbgi")),
  server = function(input, output, session) {
    output$my_cbgi <- renderUI(my_checkboxGroupInput("variable", "Variable:",
                                                     choices = my_names,
                                                     selected=my_selected, 
                                                     colors=my_colors))
    }
  )

Now, I wanna things more dynamic -- instead of assigning a color to a choice permanently, I prefer assigning first N colors to the N chosen item. Unfortunately, the code I customized does not work the way I want.

For example, I have 6 colors, and have all six variables chosen by default, when I de-check any one of (two, three, four, five), I assume the color ones after the de-checked will update properly. let's say ('blue','red','green','purple','lemon','brown') AND ('one','two','three','four','five','six'); when I de-check 'three', I wanna see ('blue','red','green','purple','lemon') for ('one','two','four','five','six'), but the actual color is ('blue','red','purple','lemon','blue').

here is the code I used for testing:

my_names <- c('one','two','three','four','five','six')
my_selected <- c('one','two','three','four','five','six')
my_colors <-c('blue','red','green','purple','lemon','brown')

shinyApp(ui=fluidPage(uiOutput("my_cbgi")),

      server = function(input, output, session) {
        my <- reactiveValues(selected=my_selected)
        observeEvent(input$variable,{my$selected <- input$variable})
        output$my_cbgi <- renderUI(my_checkboxGroupInput("variable", "Variable:",
                                                         choices = my_names, 
                                                         selected=my$selected,
                                                         colors=my_colors[1:length(my$selected)]))
      })

Upvotes: 3

Views: 969

Answers (1)

HubertL
HubertL

Reputation: 19544

Here is an updated version of the function that will give you expected result. It uses the ignoreNULL parameter of observeEvent to track the unchecking of last checked box. I had to add a variable to ignore the first call that would unselect all your initial selection:

my_checkboxGroupInput <- function(variable, label, choices, selected, colors){
    choices_names <- choices
    if(length(names(choices))>0) choices_names <- names(choices)
    my_colors <- rep("black", length(choices))
    is_selected <- choices %in% selected
    my_colors[is_selected] <- colors[1:sum(is_selected)]
    div(id=variable,class="form-group shiny-input-checkboxgroup shiny-input-container shiny-bound-input",
        HTML(paste0('<label class="control-label" for="',variable,'">',label,'</label>')),
        div( class="shiny-options-group",
             HTML(paste0('<div class="checkbox" style="color:', my_colors, '">',
                         '<label>',
                         '<input type="checkbox" name="', variable, 
                         '" value="', choices, 
                         '"', ifelse(is_selected, 'checked="checked"', ''), 
                         '/>',
                         '<span>', choices_names,'</span>',
                         '</label>',
                         '</div>', collapse = " "))
        )
    )
  }


my_names <- c('one','two','three','four','five','six')
my_selected <- c('one','two','three','four','five','six')
my_colors <-c('blue','red','green','purple','lemon','brown')

shinyApp(ui=fluidPage(uiOutput("my_cbgi")),

         server = function(input, output, session) {
           my <- reactiveValues(selected=my_selected, firt_call_ignore=TRUE)
           output$my_cbgi <- renderUI(my_checkboxGroupInput("variable", "Variable:",
                                                            choices = my_names, 
                                                            selected=my$selected,
                                                            colors=my_colors ))
           observeEvent(input$variable,{
             if(my$firt_call_ignore)
               my$firt_call_ignore=FALSE
             else
               my$selected <- input$variable
             }, ignoreNULL = FALSE)
         })

Upvotes: 2

Related Questions