How can I display a dataframe in a Shiny app as a grid, and not a table?

I am brand new to R and Shiny. I have some data in a dataframe.

I can display the dataframe as a table with DataTables.
However, I would like to display the data as a grid with N columns, so that every N rows from the data frame are shown in the same row.

As shown in the image above, I have gotten a grid to show up by using HTML to render the data frame directly.
But the next step is where I am stuck, which is I want to be able to show a modal dialog when a cell in the grid is clicked.
I have that working in the data table, but I haven't been able to figure out how to make a div clickable, such that when handling the event I know which cell was clicked?

library("shiny")
library("tidyr")
library("tidyverse")
library("dplyr")
library("shinydashboard")



# generate html grid from data frame
getHTML <- function (frames) {
  innerhtml = '<div class="grid-container">'
  for (row in 1:(nrow(frames))) {
      id <- frames[row, "id"]
      name  <- frames[row, "names"]
        row_html = '<div class="grid-item">'
        row_html = paste(row_html, '<span>Name: ' , name, "id ", row , '</span>')
        row_html = paste(row_html, '</div>')
        
         innerhtml = paste(innerhtml, row_html)
  }
  paste(innerhtml, "</div>")
  return (innerhtml)
}

#show modal dialog for player id and name
plotModal <- function(id, name) {
  modalDialog(
         p(paste("Player  # ", id, ", " , name,", was clicked")),
         title = paste("Player " , id),
        
        easyClose = TRUE
      )
}

ui <- dashboardPage(
  # Application title
  dashboardHeader(title = "Dashboard"),

  dashboardSidebar(
      h3("Filters")
    ),

    dashboardBody(
        tags$head(tags$style(HTML('
      .grid-container {
        display: grid;
        grid-template-columns: auto auto auto auto;
 
        }
        .grid-item {
        background-color: rgba(255, 255, 255, 0.8);
        border: 1px solid rgba(0, 0, 0, 0.8);
          padding: 20px;


        }'))),

      fluidRow(
        box(title="Render as table", column(width=12, DT::dataTableOutput("player_table"))),
       box(title="Render as Grid", column(width=12,   uiOutput("player_grid")))
      )
    )
)


server <- function(input, output, session) {
# data to be rendered
    frames = data.frame(names= c("james","kyle", "sally","hannah","jeff","kurt"), ids=c(1:6))

  output$player_table <- DT::renderDataTable({
    DT::datatable(frames, rownames=FALSE,  selection = 'single')
  })

        

#when a row in the table is clicked, show popup
  observeEvent(input$player_table_cell_clicked, {
    info = input$player_table_cell_clicked
    # do nothing if not clicked yet, or the clicked cell is not in the 1st column
    if (is.null(info$value)) {
      return()
    }
  
    row = frames[info$row, ]
    showModal(plotModal(row$id, row$names))
  })

output$player_grid <- renderUI ({
      HTML(getHTML(frames))
  })
  
}

# Create Shiny app ----
shinyApp(ui, server,options=list(host="0.0.0.0", port=8015))

Thank you!

Found an answer on stack overflow:

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.