I have a nested list called inputs
:
library(htmltools)
library(shiny)
inputs = tagList(
selectInput('first', 'FIRST', letters),
checkboxInput('second', '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 modify all sublists who have class shiny.tag
and whose name
element equals label
(see inputs[[1]][["children"]][[1]]
for an example of such a sublist) but preserve the original structure of the list while doing so.
To do this, I define a recursive function hideLabel
:
hideLabel <- function(tag.list) {
lapply(tag.list, function(x) {
if(inherits(x, 'shiny.tag')) {
if(x$name == 'label') {
tagAppendAttributes(x, style = 'display:none;')
} else {
hideLabel(x$children)
}
} else {
return(x)
}
})
}
Here is the output of applying hideLabel to the inputs list:
res = hideLabel(inputs)
str(res, max.level = 1)
List of 2
$ :List of 2
$ :List of 1
As shown above, hideLabel does not return a list of the same structure as the original list inputs (compare the output of str in the first code chunk with the output of str in the third chunk above). I was wondering if someone could help me understand why the function is doing this and how it could be modified? I have tried rewriting it several times to no avail.
Update:
I got it to work after thinking about what the function was returning at each stage. Here is the updated function:
hideLabel <- function(x) {
children = x$children
x$children = lapply(children, function(y) {
if(inherits(y, 'shiny.tag')) {
if(y$name == 'label') tagAppendAttributes(y, style = 'display:none;') else hil(y)
} else y
})
return(x)
}
This preserves the structure of the original list:
inputs_new = lapply(inputs, hideLabel)
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"
NOTE: The class of the overall list changes though from shiny.tag.list
to just list
. Would anyone know how to prevent this from happening? I know I could use do.call(tagList, inputs_new)
to manually add the shiny.tag.list
class back on but that seems hacky.
tagAppendAttributes
to make this a reproducible example – Defolianthtmltools
package, I have included alibrary
call in the header of my code so the result should be reproducible. – TranquilI would like to modify all sublists who have class shiny.tag and whose name element equals label
modify to what? Also why do you thinktagAppendAttributes
would change the class ofx
in your function ? – Insultshiny.tag
and whose first element (name
) equalslabel
by applying thetagAppendAttributes
function to them as so:tagAppendAttributes(x, style = 'display:none;')
.tagAppendAttributes
does not change the class of the tag. It's thehideLabel
function that changes the class of tags that do not satisfy thex$name == 'label'
condition during the recursion. Does this clarify it? – TranquiltagAppendAttributes(x, style = 'display:none;')
to all label tags in theinputs
list (label tags are all sublists with classshiny.tag
AND name == 'label') while preserving the original structure of theinputs
list (the structure is shown in thestr
output in the first chunk in my post). – Tranquil