在闪亮的流中创建动态数量的卡片元素

时间:2019-04-18 08:26:02

标签: html r shiny

我喜欢用卡片元素填充闪亮的应用程序中的某个区域。如果没有足够的空间,这些项目将流入下一行。这可以通过flowLayout来实现。

enter image description here

但是我不知道物品的数量,所以我需要循环创建卡片元素。但是当我在flowLayout中使用lapply时,所有元素都显示在彼此下面。

如何解决此问题,使项目以相邻的行显示?

library(shiny)

card <- function(.img, .species, .sepal.length) {
  HTML(
    paste0(
      '<div class="card">
      <img src="', .img, '" style="width:100%">
      <div class="container">
      <h4><i>', .species, '</i></h4>
      <hr>
      <p>Sepal Length: ', .sepal.length, '</p>
      </div>
      </div>')
  )
}

img.src <- "https://www.plant-world-seeds.com/images/item_images/000/007/023/large_square/iris_baby_blue.jpg?1500653527"

ui <- fluidPage(
  tags$head(tags$style('.card {
                         width: 250px;
                       clear: both;
                       /* Add shadows to create the "card" effect */
                       box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
                       transition: 0.3s;
                       }
                       /* On mouse-over, add a deeper shadow */
                       .card:hover {
                       box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
                       }
                       /* Add some padding inside the card container */
                       .container {
                       width: 250px;
                       padding: 2px 16px;
                       }')),
  uiOutput("cards")
)

server <- function(input, output, session) {

  # This looks as expected

  # output$cards <- renderUI({
  #   shiny::flowLayout(
  #     cellArgs = list(
  #       style = "
  #           width: auto;
  #           height: auto;
  #           margin: 5px;
  #           "),
  #     card(img.src,
  #          .species = iris[1, "Species"],
  #          .sepal.length = iris[1, "Sepal.Length"]),
  #     card(img.src,
  #          .species = iris[2, "Species"],
  #          .sepal.length = iris[2, "Sepal.Length"]),
  #     card(img.src,
  #          .species = iris[3, "Species"],
  #          .sepal.length = iris[3, "Sepal.Length"]),
  #     card(img.src,
  #          .species = iris[4, "Species"],
  #          .sepal.length = iris[4, "Sepal.Length"])
  #   )
  # })

  # Now elements are below each other when using lapply

  output$cards <- renderUI({
    shiny::flowLayout(
      cellArgs = list(
        style = "
        width: auto;
        height: auto;
        margin: 5px;
        "),
      lapply(1:4, function(.x) card(img.src,
                       .species = iris[.x, "Species"],
                       .sepal.length = iris[.x, "Sepal.Length"]))
      )
  })
}

shinyApp(ui, server)

1 个答案:

答案 0 :(得分:1)

上面的评论链接到了一个有效的答案,但是有一种更简单的方法。

我们可以使用lapply来扩展自变量,而不是使用flowLayout(使列表混乱,do.call)。

更新的服务器功能:

server <- function(input, output, session) {

  output$cards <- renderUI({

    # First make the cards
    args <- lapply(1:4, function(.x) card(img.src,
                                  .species = iris[.x, "Species"],
                                  .sepal.length = iris[.x, "Sepal.Length"]))

    # Make sure to add other arguments to the list:
    args$cellArgs <- list(
      style = "
        width: auto;
        height: auto;
        margin: 5px;
        ")

    # basically the same as flowLayout(cards[[1]], cards[[2]],...)
    do.call(shiny::flowLayout, args)

  })
}