0

I have a tagList of two Shiny inputs, inputs. I would like to extract the label tag for each input. I was hoping that htmltools had a getter function to achieve this but in the absence of one I've defined a function, getLabel, that recurses through the input list and extracts the sublists whose name element equals the value label. Here is my code:

library(htmltools)
library(shiny)

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

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'))) {

      getLabel2(x$children)

    } else {

      return(x)

    }

  })
}

labels = getLabel(inputs)

The problem is that the resulting list includes zero-length sublists. My desired output is a list of two elements (the label for each input) of class 'shiny-tag'. How can I modify my function to achieve this? Also, can this be done in htmltools? I can't find any relevant getters in the package manual.

user51462
  • 1,658
  • 2
  • 13
  • 41

1 Answers1

1

You could do:

inputs %>% toString %>% read_html %>% html_nodes(xpath = "//label") %>% html_text() %>% list

Explanation:

shiny inputs are basically html code. The same holds for tagList(). (You can check it by running selectInput or your variable inputs in your console,...). So you can use xpath/css to parse the resulting xml document.

There might be another way with htmltools, this just came to my mind when thinking about that shiny inputs are basically html code.

Reproducible example:

library(shiny)
library(rvest)
library(magrittr)

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

inputs %>% toString %>% read_html %>% 
   html_nodes(xpath = "//label") %>% html_text() %>% list
Tonio Liebrand
  • 17,189
  • 4
  • 39
  • 59
  • Thank you @BigDataScientist, this is a nice solution but unfortunately as specified in my post I require the output to be a list of two tags with class `shiny.tag`. So I need to preserve the structure of the label tags when extracting them. Is there a way to do this using a recursive function as in the post? – user51462 Sep 29 '19 at 03:39
  • The function I've defined in my post nearly gets me there, except that the resulting list includes `NULL`s. I just need help tweaking that function 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. – user51462 Sep 29 '19 at 04:47
  • ah sry i missread that. Will take a look if i can modify your functions. – Tonio Liebrand Sep 30 '19 at 17:03
  • No problem, thanks for looking into it. I have still upvoted your solution. – user51462 Oct 01 '19 at 08:20