проблема
При динамическом создании 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")
)
)
)
Если я теперь хочу вставить эту структуру в теги пользовательского интерфейса, я обычно получаю что-то вроде:
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
с. Я также взглянул на некоторые r-пакеты, такие как whisker
, но они, похоже, имеют то же ограничение и не поддерживают теги или структуры списков.
Спасибо!
источник
www
папке, а затем применить таблицы стилей?htmlTemplate()
бы условности и петли аля руль, усы, веточку ...Ответы:
Мне нравится создавать компонуемые и повторно используемые элементы пользовательского интерфейса, используя функции, которые создают блестящие HTML-теги (или
htmltools
теги). Из вашего примера приложения я мог бы идентифицировать элемент «страница», а затем два контейнера общего содержимого, а затем создать некоторые функции для них:И тогда я мог бы составить свой интерфейс с чем-то вроде этого:
В любое время, когда мне нужно настроить стиль или HTML-элемент, я просто перейду прямо к функции, которая генерирует этот элемент.
Кроме того, я только что добавил данные в этом случае. Я думаю, что структура данных в вашем примере действительно смешивает данные с проблемами пользовательского интерфейса (стилизация, теги HTML), что может объяснить некоторую запутанность. Единственные данные, которые я вижу, - это «оранжевый» в качестве заголовка и «импичмент» / «инструмент» в качестве содержимого.
Если у вас более сложные данные или вам нужны более специфичные компоненты пользовательского интерфейса, вы можете снова использовать функции, такие как строительные блоки:
Надеюсь, это поможет. Если вы ищете лучшие примеры, вы можете проверить исходный код за элементами ввода и вывода Shiny (например
selectInput()
), которые по сути являются функциями, которые выплевывают HTML-теги. Также может работать шаблонизатор, но в этом нет особой необходимости, когда у вас уже естьhtmltools
+ полная мощность R.источник
Может быть, вы могли бы рассмотреть
glue()
иget()
.получить():
get()
может превращать строки в переменные / объекты.Таким образом, вы могли бы сократить:
в
(см. пример ниже).
клей ():
glue()
предоставляет альтернативуpaste0()
. Это может быть более читабельным, если вы добавите в строку множество строк и переменных. Я предполагаю, что это также выглядит близко к синтаксису желаемого результата.Вместо:
Вы бы написали:
Ваш пример упростит до:
С помощью:
Альтернативы:
Я думаю, что htmltemplate - хорошая идея, но еще одной проблемой являются нежелательные пробелы: https://github.com/rstudio/htmltools/issues/19#issuecomment-252957684 .
источник