Search code examples
rshinyshinywidgets

updateRadioGroupButtons removes css


I'm using radioGroupButtons with different colors based on this code: https://github.com/dreamRs/shinyWidgets/issues/41# Now I want to be able to update the choices, but the colors disappears when i'm updating with updateRadioGroupButtons. If i'm only updating the selected value everything is fine, but if I update choiceValues and choiceNames the colors disappears.

Reproducible code:

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
    radioGroupButtons(
        inputId = "sent", 
        label = "Sentiment", 
        choiceValues = -2:1, 
        checkIcon = list(yes = icon("check")),
        choiceNames = paste0(-2:1),
        justified = TRUE, width = "300px"
    ),
    tags$script("$(\"input:radio[name='sent'][value='-2']\").parent().css('background-color', '#DE6B63');"),
    tags$script("$(\"input:radio[name='sent'][value='-1']\").parent().css('background-color', '#EDB6B2');"),
    tags$script("$(\"input:radio[name='sent'][value='0']\").parent().css('background-color', '#E7E7E7');"),
    tags$script("$(\"input:radio[name='sent'][value='1']\").parent().css('background-color', '#B2EDB5');"),
    tags$script("$(\"input:radio[name='sent'][value='2']\").parent().css('background-color', '#7EF373');"),
    verbatimTextOutput(outputId = "res"),
    actionButton(inputId = "update", label = "Update")
)

server <- function(input, output, session) {
    
    output$res <- renderPrint(input$sent)
    
    observeEvent(input$update, {
        updateRadioGroupButtons(session = session, inputId = "sent", choiceValues = -2:2, choiceNames = paste0(-2:2))
    }, ignoreInit = TRUE)
}

shinyApp(ui, server)

Solution

  • There are maybe easier solutions, but if we setup a mutation observer then we can apply the javascript each time a change (mutation) is detected.

    library(shiny)
    library(shinyWidgets)
    
    ui <- fluidPage(
      radioGroupButtons(
        inputId = "sent", 
        label = "Sentiment", 
        choiceValues = -2:1, 
        checkIcon = list(yes = icon("check")),
        choiceNames = paste0(-2:1),
        justified = TRUE, width = "300px"
      ),
      tags$script("
      // this is the setting in the first instance
      $(\"input:radio[name='sent'][value='-2']\").parent().css('background-color', '#DE6B63');
    $(\"input:radio[name='sent'][value='-1']\").parent().css('background-color', '#EDB6B2');
    $(\"input:radio[name='sent'][value='0']\").parent().css('background-color', '#E7E7E7');
    $(\"input:radio[name='sent'][value='1']\").parent().css('background-color', '#B2EDB5');
    $(\"input:radio[name='sent'][value='2']\").parent().css('background-color', '#7EF373');
    
    // lets listen to changes with a mutation observer
      // select the target node
    var target = document.getElementById('sent')  
    
    // create an observer instance
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        if( document.getElementById('sent')) {
    // here we apply the formatting again
    $(\"input:radio[name='sent'][value='-2']\").parent().css('background-color', '#DE6B63');
    $(\"input:radio[name='sent'][value='-1']\").parent().css('background-color', '#EDB6B2');
    $(\"input:radio[name='sent'][value='0']\").parent().css('background-color', '#E7E7E7');
    $(\"input:radio[name='sent'][value='1']\").parent().css('background-color', '#B2EDB5');
    $(\"input:radio[name='sent'][value='2']\").parent().css('background-color', '#7EF373');
        }
      });    
    });
    
    // configuration of the observer:
    // it works with childList although I would expect it to work with characterData
    var config = {
      childList: true,
      subtree: true,
      attruibutes: true,
      characterData: true
    };
    
    // pass in the target node, as well as the observer options
    observer.observe(target, config); 
                  "),
      
      verbatimTextOutput(outputId = "res"),
      actionButton(inputId = "update", label = "Update")
    )
    
    server <- function(input, output, session) {
      
      output$res <- renderPrint(input$sent)
      
      observeEvent(input$update, {
        updateRadioGroupButtons(session = session, inputId = "sent", choiceValues = -2:2, choiceNames = paste0(-2:2), checkIcon = list(yes = icon("check")))
      }, ignoreInit = TRUE)
    }
    
    shinyApp(ui, server)