'Rshiny layout boxes
Having trouble searching the right words for this particular issue I am having.
I wanted boxes to go around this image of the car, but given the height of the image, it means it shifts the next fluidrow to be even further down. Is there a way to get the boxes to look like where I have drawn the red boxes? But more so the boxes next to the car image on row 3 (I don't expect anyone to code the 4th fluid row!).
I tried to incorporate the vertical layout but it just made everything vertical.
code: and just use any image to replace below
library(shinydashboard)
library(shiny)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(disable = TRUE),
dashboardSidebar(disable = TRUE),
dashboardBody(
useShinyjs(),
dashboardBody(
# the first row
fluidRow(
box( id = "box1",
h4(strong(textOutput("box1"))),
p(textOutput("box1_sub")),
width = 2,
solidHeader = TRUE
),
box( id = "box2",
h4(strong(textOutput("box2"))),
p(textOutput("box2_sub")),
width = 2,
solidHeader = TRUE,
background = "blue"
),
box( id = "box3",
h4(strong(textOutput("box3"))),
p(textOutput("box3_sub")),
width = 2,
solidHeader = TRUE
),
box( id = "box4",
h4(strong(textOutput("box4"))),
p(textOutput("box4_sub")),
width = 2,
solidHeader = TRUE,
background = "yellow"
),
box( id = "box5",
h4(strong(textOutput("box5"))),
p(textOutput("box5_sub")),
width = 2,
solidHeader = TRUE,
background = "purple"
),
box( id = "box6",
h4(strong(textOutput("box6"))),
p(textOutput("box6_sub")),
width = 2,
solidHeader = TRUE
)
),
br(),
# second row with car image
fluidRow(
box( id = "box7",
h4(strong(textOutput("box7"))),
p(textOutput("box7_sub")),
width = 2,
solidHeader = TRUE,
background = "green"
),
box( id = "box8",
h4(strong(textOutput("box8"))),
p(textOutput("box8_sub")),
width = 2,
solidHeader = TRUE,
background = "green"
),
box( uiOutput("car_image"),
width = 4
),
box( id = "box13",
h4(strong(textOutput("box13"))),
p(textOutput("box13_sub")),
width = 2,
solidHeader = TRUE,
background = "green"
),
box( id = "box14",
h4(strong(textOutput("box14"))),
p(textOutput("box14_sub")),
width = 2,
solidHeader = TRUE,
background = "green"
)
),
br(),
# third row
fluidRow(
box( id = "box10",
h4(strong(textOutput("box10"))),
p(textOutput("box10_sub")),
width = 2,
solidHeader = TRUE
)
),
br(),
# fourth row
fluidRow(
box( id = "box11",
h4(strong(textOutput("box11"))),
p(textOutput("box11_sub")),
width = 2,
solidHeader = TRUE
),
box( id = "box12",
h4(strong(textOutput("box12"))),
p(textOutput("box12_sub")),
width = 2,
solidHeader = TRUE
)))))
server <- function(input, output) {
output$car_image <- renderUI({
img(src='/image.png', width = '100%')})
output$box1 <- renderText({"box1"})
output$box1_sub<- renderText({"box1_sub"})
output$box2 <- renderText({"box2"})
output$box2_sub <- renderText({"box2_sub"})
output$box3 <- renderText({"box3"})
output$box3_sub <-renderText({"box3_sub"})
output$box4<- renderText({"box4"})
output$box4_sub <- renderText({"box4_sub"})
output$box5 <- renderText({"box5"})
output$box5_sub <- renderText({"box5_sub"})
output$box6 <- renderText({"box6_sub"})
output$box6_sub <- renderText({"box6_sub"})
output$box7<- renderText({"box7"})
output$box7_sub <- renderText({"box7_sub"})
output$box8 <- renderText({"box8"})
output$box8_sub <- renderText({"box8_sub"})
output$box9<- renderText({"box9"})
output$box9_sub <- renderText({"box9_sub"})
output$box10<- renderText({"box10"})
output$box10_sub <- renderText({"box10_sub"})
output$box11<- renderText({"box11"})
output$box11_sub <- renderText({"box11_sub"})
output$box12<- renderText({"box12"})
output$box12_sub <- renderText({"box12_sub"})
output$box13<- renderText({"box13"})
output$box13_sub <- renderText({"box13_sub"})
output$box14<- renderText({"box14"})
output$box14_sub <- renderText({"box14_sub"})
}
shinyApp(ui = ui, server = server)
Solution 1:[1]
Given your code I will try to help you with other aspects of your App as well.
Set up
Recommedation 1: Use funcional programming
Hadley Wickham in the chapter 18 of his book mastering shiny cover the idea of using functions to reduce code duplication in your apps. Taking this in consideration, let's build a function that taking and id as argument, returns a box.
With this function you can control any alement of the box. And, with the argument imagenbox you can tell if the box will contain the car image.
create_box <- \(
id, imagenbox = FALSE, width = 12,
background = 'green',solid_header = TRUE
){
boxId <- paste0('box', id)
subtilteId <- paste0('box', id, "_sub")
if(imagenbox) {
return(
box(
id = boxId, class = 'imagen_box',
uiOutput('car_image'),
width = width
)
)
}
box(id = boxId,
h4(strong(textOutput(boxId))),
p(textOutput(subtilteId)),
width = width,
solidHeader = solid_header
)
}
Now that you have this function, let's prepare the list of argument to loop over that function and generate the boxes in you app UI.
Wiht this two vectors we are going to create 13 boxes, and the box number 6 will be the box with the car image.
boxes <- 1:13
car_imagen_index <- c(rep(FALSE, 5), TRUE, rep(FALSE, 7))
App User interface
With an app as complex as this one, you have to think out of the box and use not only shiny code to arrange and style the visual elements. I will add a css file to include/make the grid layout you need.
The css file content is this
/* Display grid for the box container with 4 columns */
body > div.wrapper > div > section > div > section {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
}
/* Element 6 (the one with the image, remember) to span across
two rows and colums
*/
body > div > div > section > div > section > div:nth-child(6) {
grid-row: span 2;
grid-column: span 2;
}
Note: A ccs file is just a text file with that extension. This article is a good introduction
ui <- dashboardPage(
dashboardHeader(disable = TRUE),
dashboardSidebar(disable = TRUE),
dashboardBody(
# Here I include the css file
includeCSS('grid-style.css'),
useShinyjs(),
dashboardBody(
# Function programming to generate the boxes
map2(boxes, car_imagen_index, ~create_box(.x, .y))
)
)
)
In your server you can use functional programming as well. For example, the title and subtitle of the boxes will be generated with a iteretive process.
server <- function(input, output) {
# render the car image
output$car_image <- renderUI({
img(src='https://www.elcarrocolombiano.com/wp-content/uploads/2021/04/20210420-WORLD-CAR-OF-THE-YEAR-VOLKSWAGEN-ID-4-01.jpg', width = '100%')})
# render the boxes title and subtitle
lapply(boxes, \(id) {
boxId = paste0('box', id)
subtitleId = paste0('box', id, '_sub')
output[[boxId]] <- renderText(boxId)
output[[subtitleId]] <- renderText(subtitleId)
})
}
shinyApp(ui = ui, server = server)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |


