Problema
Ao criar dinamicamente ui-elementos ( shiny.tag
, shiny.tag.list
...), muitas vezes eu achar que é difícil separá-lo de minha lógica de código e geralmente acabam com uma bagunça complicada de nested tags$div(...)
, misturado com loops e instruções condicionais. Embora chato e feio de se ver, também é passível de erros, por exemplo, ao fazer alterações nos modelos html.
Exemplo reproduzível
Digamos que eu tenho a seguinte estrutura de dados:
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")
)
)
)
Se agora quero inserir essa estrutura em tags de interface do usuário, geralmente acabo com 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 você pode ver, isso já é bastante confuso e ainda nada comparado aos meus exemplos reais.
Solução desejada
Eu esperava encontrar algo próximo a um mecanismo de modelo para R, que permitisse definir modelos e dados separadamente :
# 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}}"
)
)
Tentativas anteriores
Primeiro, pensei que shiny::htmlTemplate()
poderia oferecer uma solução, mas isso funcionaria apenas com arquivos e seqüências de texto, não com shiny.tag
s. Também observei alguns pacotes r como o whisker
, mas esses parecem ter a mesma limitação e não suportam tags ou estruturas de lista.
Obrigado!
fonte
www
pasta e aplicar as folhas de estilo?htmlTemplate()
permitiria condicionais e loops guidão ala, bigode, galho ...Respostas:
Gosto de criar elementos de interface do usuário composíveis e reutilizáveis usando funções que produzem tags HTML brilhantes (ou
htmltools
tags). No seu exemplo de aplicativo, eu pude identificar um elemento "page" e, em seguida, dois contêineres de conteúdo genéricos e, em seguida, criar algumas funções para eles:E então eu poderia compor minha interface do usuário com algo assim:
Sempre que eu precisar ajustar o estilo ou o HTML de um elemento, basta ir direto para a função que gera esse elemento.
Além disso, acabei de incluir os dados neste caso. Eu acho que a estrutura de dados no seu exemplo realmente combina dados com preocupações da interface do usuário (estilo, tags HTML), o que pode explicar alguns dos problemas. Os únicos dados que vejo são "laranja" como cabeçalho e "impeach" / "tool" como conteúdo.
Se você tiver dados mais complicados ou precisar de componentes de interface do usuário mais específicos, poderá usar as funções novamente, como blocos de construção:
Espero que ajude. Se você estiver procurando por exemplos melhores, pode verificar o código-fonte por trás dos elementos de entrada e saída do Shiny (por exemplo
selectInput()
), que são essencialmente funções que emitem tags HTML. Um mecanismo de modelagem também pode funcionar, mas não há necessidade real quando você já temhtmltools
+ a potência total de R.fonte
Talvez você possa considerar investigar
glue()
eget()
.pegue():
get()
pode transformar strings em variáveis / objetos.Então você pode diminuir:
para
(veja o exemplo abaixo).
cola():
glue()
fornece uma alternativa parapaste0()
. Poderia ser mais legível se você concentrar muitas seqüências de caracteres e variáveis em uma sequência. Suponho que ele também se parece com a sintaxe do resultado desejado.Ao invés de:
Você escreveria:
Seu exemplo seria simplificado para:
Usando:
Alternativas:
Acho que htmltemplate é uma boa ideia, mas outro problema são os espaços em branco indesejados: https://github.com/rstudio/htmltools/issues/19#issuecomment-252957684 .
fonte