0

In my reprex below, Number duplicates the inputs. I am stuck on how to achieve two things.

  1. If the Contractor radio button option is selected, show a text input with label "Name of Contractor".

  2. How can I have the radio button input set as empty? I know selected = character(0) achieves this, but it causes another challenge: if an option is selected, and then Number is changed, the radio button selection will disappear. In my reprex, the radio button selection will not be affected after Number is changed, but the default selection is the first choice, whereas I would like the default to be empty.

library(shiny)

ui <- fluidPage(
  numericInput("n", "Number", value = 1),
  uiOutput("col")
)


server <- function(input, output, session) {
  
  # Dynamic UI: Multiple Controls -------------------------------------------
  
  col_names <- reactive(paste0("staff_attended_", seq_len(input$n)))
  
  output$col <- renderUI({
    map(
      col_names(), 
      ~ tagList(
          selectInput(
            .x,
            label = "Staff Attended",
            choices = letters,
            selected = isolate(input[[.x]]),
            multiple = TRUE
          ),
          
          radioButtons(
            paste0(.x, "_type"), 
            "Staff Attended: Shift/Call-In/Contractor?",
            choices = c("Shift", "Call-In", "Contractor"),
            selected = isolate(input[[paste0(.x, "_type")]])
          )
          
      )
    )
  })
}

shinyApp(ui, server)
Jan
  • 2,245
  • 1
  • 2
  • 16
its.me.adam
  • 333
  • 2
  • 11
  • How important is the radio button question? As you already saw the `character(0)` workaround, you may have seen that this it is not really state of the art to have something like this as discussed in some [other](https://stackoverflow.com/questions/54772944/reset-radiobuttons-in-shiny-to-empty-value) questions. I managed to get question 1 to work but it even more complicates it with question 2. Would a `checkboxGroupInput` be an alternative? – Jan Jul 29 '23 at 22:38
  • Yes a `checkboxGroupInput` would be an alternative, or anything else that achieves the same functionality. – its.me.adam Jul 31 '23 at 18:06

1 Answers1

1

Here is one example.

Question 1: If the Contractor radio button option is selected, show a text input with label "Name of Contractor".

Therefore we can use a conditionalPanel which contains a textInput. The condition can be written as

paste0(
   "(document.querySelector('input[name=\"",
   .x,
   "_type\"]:checked') || {value: 'dummy'}).value === 'Contractor'"
)

Explanation:

  • The document.querySelector call aims for the checked value of the radioButtons. The relevant checkbox id is assigned by .x inside your map call. It shall return TRUE if this value is "Contractor".
  • Since you would like to have empty radioButtons when starting the app, the querySelector would be null while being in this state. Hence, the || {value: 'dummy'}) will yield a dummy value such that there won't be an error and the textInput is hidden by the start of the app. Otherwise, the || operator will short-circuit.

enter image description here

Question 2: How can I have the radio button input set as empty? I know selected = character(0) achieves this, but it causes another challenge: if an option is selected, and then Number is changed, the radio button selection will disappear...

In order to retain the selection when the number is changed, we put an observeEvent on input$n and use an updateRadioButtons, which will affect the selected parameter using isolate.

observeEvent(input$n, {
    map(col_names(),
        ~ tagList(
            updateRadioButtons(session, paste0(.x, "_type"),
                               selected = isolate(input[[paste0(.x, "_type")]]))
        ))
})

enter image description here

Complete minimal example:

library(shiny)

ui <- fluidPage(numericInput("n", "Number", value = 1),
                uiOutput("col"))


server <- function(input, output, session) {
    # Dynamic UI: Multiple Controls -------------------------------------------
    
    col_names <-
        reactive(paste0("staff_attended_", seq_len(input$n)))
    
    observeEvent(input$n, {
        map(col_names(),
            ~ tagList(
                updateRadioButtons(session, paste0(.x, "_type"),
                                   selected = isolate(input[[paste0(.x, "_type")]]))
            ))
    })
    
    output$col <- renderUI({
        map(col_names(),
            ~ tagList(
                selectInput(
                    .x,
                    label = "Staff Attended",
                    choices = letters,
                    selected = isolate(input[[.x]]),
                    multiple = TRUE
                ),
                
                radioButtons(
                    paste0(.x, "_type"),
                    "Staff Attended: Shift/Call-In/Contractor?",
                    choices = c("Shift", "Call-In", "Contractor"),
                    selected = character(0)#isolate(input[[paste0(.x, "_type")]])
                ),
                
                conditionalPanel(
                    paste0(
                        "(document.querySelector('input[name=\"",
                        .x,
                        "_type\"]:checked') || {value: 'dummy'}).value === 'Contractor'"
                    ),
                    textInput("NameContractor", "Name of Contractor")
                )
                
            ))
    })
}

shinyApp(ui, server)
Jan
  • 2,245
  • 1
  • 2
  • 16