Masalah
Ketika secara dinamis membuat elemen ui ( shiny.tag
,, shiny.tag.list
...), saya sering merasa sulit untuk memisahkannya dari logika kode saya dan biasanya berakhir dengan kekacauan bersarang tags$div(...)
, dicampur dengan loop dan pernyataan kondisional. Meskipun menjengkelkan dan jelek untuk dilihat, itu juga rawan kesalahan, misalnya ketika membuat perubahan ke html-templates.
Contoh yang bisa direproduksi
Katakanlah saya memiliki struktur data berikut:
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")
)
)
)
Jika sekarang saya ingin mendorong struktur ini menjadi ui-tag, saya biasanya berakhir dengan sesuatu seperti:
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)
Seperti yang Anda lihat, ini sudah sangat berantakan dan masih tidak seberapa dibandingkan dengan contoh nyata saya.
Solusi yang diinginkan
Saya berharap menemukan sesuatu yang dekat dengan mesin templating untuk R, yang akan memungkinkan untuk mendefinisikan template dan data secara terpisah :
# 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}}"
)
)
Upaya sebelumnya
Pertama, saya pikir itu shiny::htmlTemplate()
bisa menawarkan solusi, tetapi ini hanya akan bekerja dengan file dan string teks, bukan shiny.tag
s. Saya juga telah melihat beberapa paket-r seperti kumis
, tetapi mereka tampaknya memiliki batasan yang sama dan tidak mendukung tag atau struktur daftar.
Terima kasih!
sumber
www
folder dan kemudian menerapkan style sheet?htmlTemplate()
akan memungkinkan untuk conditional dan loop ala setang, kumis, ranting ...Jawaban:
Saya suka membuat elemen UI komposable dan dapat digunakan kembali menggunakan fungsi yang menghasilkan tag (atau
htmltools
tag) Shiny HTML . Dari contoh aplikasi Anda, saya dapat mengidentifikasi elemen "halaman", dan kemudian dua wadah konten umum, dan kemudian membuat beberapa fungsi untuk itu:Dan kemudian saya bisa membuat UI saya dengan sesuatu seperti ini:
Setiap kali saya perlu mengubah style atau HTML suatu elemen, saya langsung saja ke fungsi yang menghasilkan elemen itu.
Juga, saya baru saja menggarisbawahi data dalam kasus ini. Saya pikir struktur data dalam contoh Anda benar-benar mencampur data dengan masalah UI (gaya, tag HTML), yang mungkin menjelaskan beberapa kekusutan. Satu-satunya data yang saya lihat adalah "oranye" sebagai header, dan "impeach" / "alat" sebagai konten.
Jika Anda memiliki data yang lebih rumit atau memerlukan komponen UI yang lebih spesifik, Anda dapat menggunakan fungsi lagi seperti blok bangunan:
Semoga itu bisa membantu. Jika Anda mencari contoh yang lebih baik, Anda dapat memeriksa kode sumber di belakang elemen input dan output Shiny (misalnya
selectInput()
), yang pada dasarnya adalah fungsi yang mengeluarkan tag HTML. Mesin templating juga bisa bekerja, tetapi tidak ada kebutuhan nyata ketika Anda sudah mendapatkanhtmltools
+ kekuatan penuh dari R.sumber
Mungkin Anda bisa mempertimbangkan untuk melihat
glue()
danget()
.Dapatkan():
get()
dapat mengubah string menjadi variabel / objek.Jadi Anda dapat mempersingkat:
untuk
(lihat contoh di bawah).
lem():
glue()
menyediakan alternatif untukpaste0()
. Ini bisa lebih mudah dibaca jika Anda memusatkan banyak string dan variabel ke string. Saya menganggap itu juga terlihat dekat dengan sintaks dari hasil yang Anda inginkan.Dari pada:
Anda akan menulis:
Contoh Anda akan disederhanakan menjadi:
Menggunakan:
Alternatif:
Saya pikir htmltemplate adalah ide yang bagus, tetapi masalah lain adalah spasi putih yang tidak diinginkan: https://github.com/rstudio/htmltools/issues/19#issuecomment-252957684 .
sumber