R Shiny - Manipulating a `tagList` of Shiny inputs

I have a tagList (inputs) of two inputs: a selectInput and a checkboxInput:

inputs = tagList(
  selectInput('first', 'FIRST', letters), 
  checkboxInput(inputId = 'second', label = 'SECOND')
)

str(inputs, max.level = 1)
List of 2
 $ :List of 3
  ..- attr(*, "class")= chr "shiny.tag"
  ..- attr(*, "html_dependencies")=List of 1
 $ :List of 3
  ..- attr(*, "class")= chr "shiny.tag"
 - attr(*, "class")= chr [1:2] "shiny.tag.list" "list"

I would like to extract the label tag for each input and was wondering if the shiny package had any getters and setters for this?

The closest thing I could find was this article on building custom inputs but the getters are JS functions.

So I attempted to write a function which recurses through the inputs list and extracts the label tag by name:

library(shiny)
library(htmltools)

getLabel2 <- function(children) {
  
  lapply(children, function(x) {
    
    if(inherits(x, 'shiny.tag')) {
      
      if(x$name == 'label') {
        
        return(x)
        
      } else {
        
        chldn = x$children
        
        if(is.list(chldn)) getLabel2(chldn)
        
      }
    }
  })
}


getLabel <- function(inputs) {
  
  lapply(inputs, function(x) {
    
    if(grepl('shiny-input-container', tagGetAttribute(x, 'class'))) {
      
      tagGetAttribute(x, 'id')
      
      getLabel2(x$children)
      
    } else {
      
      return(x)
      
    }
  })
}

Reprex:

#Reprex
inputs = tagList(
  selectInput('first', 'FIRST', letters), 
  checkboxInput(inputId = 'second', label = 'SECOND')
)

labels = getLabel(inputs)

However, there are some problems with this function:

  1. It returns a list that contains the label tags and NULLs in place of non-label tags - how can I modify it so that it returns a list of length 2 (where the first element is the label tag for input 1 and the second element is the label tag for input 2)?
  2. It doesn't check that the label tag being extracted is matched to the corresponding input tag. I wanted to do this by checking that the for attribute of the label tag (obtained using the tagGetAttribute(label_tag, 'for')) matches the id attribute of the corresponding input tag (obtained using the tagGetAttribute(input_tag, 'id')) - but I don't know if this is possible since the input tag is not easily identifiable. Is a shiny-input-container only allowed to have one label tag among its children? If so, then this check isn't necessary.

I would be grateful for any help on this as I don't know what else to try.

Hi,

It's not fully clear what you're trying to accomplish here. Would you like to hide certain elements? In that case, the shinyjs package can help.

Issues with Shiny code can stem from both the reactive Shiny code itself or the regular R code used in the functions. In order for us to help you with your question, please provide us a minimal reprocudible example (Reprex) where you provide a minimal (dummy) dataset and code that can recreate the issue. One we have that, we can go from there. For help on creating a Reprex, see this guide:

Good luck!
PJ

Oops! The reprex was on another script and it totally slipped my mind to paste it here. Thanks for the reminder @pieterjanvc, I've edited my question to make it clearer and have included the reprex :slight_smile:

Also, just to clarify, I would like to extract the label tag for each input from the tagList of inputs. I use shinyjs frequently but to my knowledge it doesn't have any getter functions that can do this.