问题
动态创建ui元素(shiny.tag
,,shiny.tag.list
...)时,我经常发现很难将其与代码逻辑分开,并且通常最终会产生混乱的嵌套嵌套tags$div(...)
,并与循环和条件语句混合在一起。尽管令人讨厌且难看,但它也容易出错,例如,在对html模板进行更改时。
可复制的例子
假设我具有以下数据结构:
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")
)
)
)
如果现在我想将此结构放入ui标签中,通常会得到如下结果:
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)
如您所见,与我的真实示例相比,这已经很混乱了,仍然一无所有。
所需的解决方案
我希望找到一些与R 的模板引擎相似的东西,从而可以分别定义模板和数据:
# 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}}"
)
)
以前的尝试
首先,我认为shiny::htmlTemplate()
可以提供一种解决方案,但这仅适用于文件和文本字符串,不适用于shiny.tag
s。我也看了一些诸如whisker的
r-package ,但是它们似乎具有相同的局限性,并且不支持标签或列表结构。
谢谢!
htmlTemplate()
将允许条件和循环ALA车把,胡子,小枝...
www
文件夹下,然后应用样式表?