Problema
Al crear dinámicamente ui-elementos ( shiny.tag
, shiny.tag.list
, ...), a menudo resulta difícil separarlo de mi lógica de código y por lo general terminan con un lío complicado de anidado tags$div(...)
, mezclado con bucles y sentencias condicionales. Si bien es molesto y feo de ver, también es propenso a errores, por ejemplo, al hacer cambios en las plantillas html.
Ejemplo reproducible
Digamos que tengo la siguiente estructura de datos:
my_data <- list(
container_a = list(
color = "orange",
height = 100,
content = list(
vec_a = c(type = "p", value = "impeach"),
vec_b = c(type = "h1", value = "orange")
)
),
container_b = list(
color = "yellow",
height = 50,
content = list(
vec_a = c(type = "p", value = "tool")
)
)
)
Si ahora quiero insertar esta estructura en etiquetas ui, generalmente termino con algo como:
library(shiny)
my_ui <- tagList(
tags$div(
style = "height: 400px; background-color: lightblue;",
lapply(my_data, function(x){
tags$div(
style = paste0("height: ", x$height, "px; background-color: ", x$color, ";"),
lapply(x$content, function(y){
if (y[["type"]] == "h1") {
tags$h1(y[["value"]])
} else if (y[["type"]] == "p") {
tags$p(y[["value"]])
}
})
)
})
)
)
server <- function(input, output) {}
shinyApp(my_ui, server)
Como puede ver, esto ya es bastante desordenado y todavía nada en comparación con mis ejemplos reales.
Solución deseada
Esperaba encontrar algo cerca de un motor de plantillas para R, que permitiera definir plantillas y datos por separado :
# syntax, borrowed from handlebars.js
my_template <- tagList(
tags$div(
style = "height: 400px; background-color: lightblue;",
"{{#each my_data}}",
tags$div(
style = "height: {{this.height}}px; background-color: {{this.color}};",
"{{#each this.content}}",
"{{#if this.content.type.h1}}",
tags$h1("this.content.type.h1.value"),
"{{else}}",
tags$p(("this.content.type.p.value")),
"{{/if}}",
"{{/each}}"
),
"{{/each}}"
)
)
Intentos anteriores
Primero, pensé que shiny::htmlTemplate()
podría ofrecer una solución, pero esto solo funcionaría con archivos y cadenas de texto, no con shiny.tag
s. También eché un vistazo a algunos paquetes r como el bigote
, pero parece que tienen la misma limitación y no admiten etiquetas o estructuras de lista.
¡Gracias!
fuente
www
carpeta y luego aplicar las hojas de estilo?htmlTemplate()
permitiría condicionales y bucles ala manillar, bigote, ramita ...Respuestas:
Me gusta crear elementos de interfaz de usuario componibles y reutilizables utilizando funciones que producen etiquetas HTML brillantes (o
htmltools
etiquetas). Desde su aplicación de ejemplo, podría identificar un elemento de "página", y luego dos contenedores de contenido genérico, y luego crear algunas funciones para ellos:Y luego podría componer mi interfaz de usuario con algo como esto:
Cada vez que necesito modificar el estilo o HTML de un elemento, simplemente voy directamente a la función que genera ese elemento.
Además, acabo de incluir los datos en este caso. Creo que la estructura de datos en su ejemplo realmente mezcla datos con preocupaciones de UI (estilo, etiquetas HTML), lo que podría explicar algunas de las enrevesadas. Los únicos datos que veo son "naranja" como encabezado e "impugnación" / "herramienta" como contenido.
Si tiene datos más complicados o necesita componentes de IU más específicos, puede usar funciones nuevamente como bloques de construcción:
Espero que ayude. Si está buscando mejores ejemplos, puede consultar el código fuente detrás de los elementos de entrada y salida de Shiny (por ejemplo
selectInput()
), que son esencialmente funciones que escupen etiquetas HTML. Un motor de plantillas también podría funcionar, pero no hay necesidad real cuando ya tieneshtmltools
+ toda la potencia de R.fuente
Tal vez podrías considerar investigar
glue()
yget()
.obtener():
get()
puede convertir cadenas en variables / objetos.Para que puedas acortar:
a
(ver el ejemplo a continuación).
pegamento():
glue()
proporciona una alternativa apaste0()
. Podría ser más legible si concéntrate muchas cadenas y variables en una cadena. Supongo que también se parece a la sintaxis del resultado deseado.En vez de:
Tu escribirías:
Su ejemplo se simplificaría a:
Utilizando:
Alternativas:
Creo que htmltemplate es una buena idea, pero otro problema son los espacios en blanco no deseados: https://github.com/rstudio/htmltools/issues/19#issuecomment-252957684 .
fuente