Is it possible to use JavaScript to control attributes of a class of UI elements, including those added dynamically using insertUI
? In this scenario, a colored box is inserted each time a button is pressed. The color is meant to change based on user input but only affects the initial div and not subsequent additions.
The issue arises from the script defined within the UI not targeting the additional divs. How can we modify the script to apply changes to all divs with the matching Id prefix?
library(shiny)
library(magrittr)
# Function to insert a colored box
insertBox = function(Id) {
boxDiv = tags$div(id = paste0("color_", Id),
style = "height:30px; width: 30px; background-color: blue;"
)
return(boxDiv)
}
# Script to update attribute values for matching Id prefixes
jsChangeDivAttr = function(event, Id, attribute) {
script = tags$script(HTML(paste0("$(document).on('shiny:inputchanged', function(event) {
if(event.name == '", event, "') {
var divs = document.querySelectorAll('[id^=\"", Id, "\"]');
for (var i = 0; i < divs.length; i++) {
divs[i].style.setProperty('", attribute, "', event.value);
}
}
});")))
return(script)
}
# UI
ui = fluidPage(
# Script for changing div properties
tags$head(
jsChangeDivAttr(event = "boxColor", Id = "color", attribute = "background-color")
),
# Select color for div
selectizeInput("boxColor", choices = c("blue", "red"), label = "Box color"),
# Button to add new div
actionButton("insertBoxButton", label = "Insert box"),
# Insert text and color divs
insertBox(0)
)
# Server
server = function(input, output, session) {
idCount = reactiveVal(0)
observe({
Id = idCount()
idCount(idCount() + 1)
insertUI(selector = paste0("#color_", Id), where = "afterEnd", ui = insertBox(idCount()))
}) %>%
bindEvent(input$insertBoxButton)
}
shinyApp(ui, server)
Edit 2023-08-30
Updated based on feedback to address issues with updating multiple divs:
script = tags$script(HTML(paste0("$(document).on('shiny:inputchanged', function(event) {
if(event.name == '", event, "') {
var divs = document.querySelectorAll('[id^=\"", Id, "\"]');
for (var i = 0; i < divs.length; i++) {
divs[i].style.setProperty('", attribute, "', event.value);
}
}
});")))