0

I am trying to apply a JS script (a 'Select all' box) to a dynamically rendered UI, but the following does not work:

library(shinyjs)

ui <- fluidPage(
    useShinyjs(),
    
    uiOutput("checkbox_ui")
)

server <- function(input, output, session) {
    
    output$checkbox_ui <- renderUI({
        checkboxGroupInput(inputId = "myCheckbox",
                           label = NULL,
                           choices = c("All", "A", "B"))
    })
    
    runjs(HTML("
        $(\"#myCheckbox input[value='All']\").click(function(e) {
            $(\"#myCheckbox input[type='checkbox']\").prop('checked', $(e.target).prop(\"checked\"));
        });
    "))
}

shinyApp(ui, server)

However, when I skip using renderUI, the JS script is ran:

library(shinyjs)

ui <- fluidPage(
    useShinyjs(),
    
    checkboxGroupInput(inputId = "myCheckbox",
                       label = NULL,
                       choices = c("All", "A", "B"))
)

server <- function(input, output, session) {
    
    runjs(HTML("
        $(\"#myCheckbox input[value='All']\").click(function(e) {
            $(\"#myCheckbox input[type='checkbox']\").prop('checked', $(e.target).prop(\"checked\"));
        });
    "))
}

shinyApp(ui, server)

Would someone know a workaround?

2 Answers 2

4

That's because the checkbox is not rendered yet when runjs is executed.

I would try:

runjs(HTML("setTimeout(function(){
        $(\"#myCheckbox input[value='All']\").click(function(e) {
            $(\"#myCheckbox input[type='checkbox']\").prop('checked', $(e.target).prop(\"checked\"));
        });
    });"))

and if that doesn't work, I would try

observeEvent(input[["myCheckbox"]], {
  runjs(HTML("
        $(\"#myCheckbox input[value='All']\").click(function(e) {
            $(\"#myCheckbox input[type='checkbox']\").prop('checked', $(e.target).prop(\"checked\"));
        });
    "))
})

EDIT

Here is a working solution, without using shinyjs:

library(shiny)

js <- paste(
  "$(document).ready(function(){",
  "  $('body').on('click', \"#myCheckbox input[value='All']\", function(e) {",
  "    var isChecked = $(e.target).prop('checked');",
  "    $(\"#myCheckbox input[value!='All']\").prop('checked', isChecked);",
  "  });",
  "});",
  sep = "\n"
)

ui <- fluidPage(
  tags$head(tags$script(HTML(js))),
  uiOutput("checkbox_ui")
)

server <- function(input, output, session) {
  
  output$checkbox_ui <- renderUI({
    checkboxGroupInput(inputId = "myCheckbox",
                       label = NULL,
                       choices = c("All", "A", "B"))
  })
  
}

shinyApp(ui, server)
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your help ! The first JS code does not have any effect, whereas the second one only works after the All box has been checked once before.
Would there be a way maybe to create an empty/invisible checkboxGroupInput in the UI, then updating it straight after it has bee created in the server function with updateCheckboxGroupInput?
You can try that, that sounds reasonable. Maybe an initial checkboxGroupInput with choices = "All" only?
@6PO0222 See my edit. A simpler working solution.
After hours trying to solve the application of a mask to inputs within uiOutput, the solution of applying it within observeEvent was perfect. I believe the problem is that, when executing the javascript function, uiOutput has not yet been built, resulting in the function not being used and canceling its execution. Therefore, another solution is to add a delay to the execution of the javascript function. shinyjs::delay(10, runjs("$(.)"))
2

The following works fine.

js <- "
        $(\"#myCheckbox input[value='All']\").click(function(e) {
            $(\"#myCheckbox input[type='checkbox']\").prop('checked', $(e.target).prop(\"checked\"));
        });
    "

library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  
  checkboxGroupInput(inputId = "myCheckbox",
                     label = NULL,
                     choices = c("All", "A", "B"))
)

server <- function(input, output, session) {
  
  observeEvent(input[["myCheckbox"]], {
    updateCheckboxGroupInput(session,"myCheckbox")
    runjs(HTML(js))
  }, ignoreNULL = FALSE)

}

shinyApp(ui, server)

output

With renderUI

ui <- fluidPage(
  useShinyjs(),
  
  uiOutput("uic")
)

server <- function(input, output, session) {
  
  output$uic <- renderUI({
    checkboxGroupInput(inputId = "myCheckbox",
                       label = NULL,
                       choices = c("All", "A", "B"))
  })
  
  observeEvent(input[["myCheckbox"]], {
    updateCheckboxGroupInput(session,"myCheckbox")
    runjs(HTML(js))
  }, ignoreNULL = FALSE)
  
}

shinyApp(ui, server)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.