0
votes

I'm finalizing my R Shiny app and I am struggling with the layout of blocks and headers. Since I have a lot of blocks, I've built my layout separately and coded it in the ui of my Shiny app using a combination of fluidRow and column. Usually each of my block then has a title, under the form p(...), followed by some information under the same form.

Since I like the idea of having a "controls" side-bar panel, the blocks on the left side of my app are used to control the different inputs I use on the app. When the user does stuff, the blocks on the left side are the ones that are impacted and modified.

I have a full row blocks that belong to the same "category". It is a dynamic UI that can have 1 to 8 blocks depending on a slider input the user can play with. What I am trying to achieve is to have one title line (either a paragraph, or a header, doesn't matter) the line above the blocks, then have the blocks, while keeping only one unit on the "control panel" on the left side.

A few images to make it clearer:

https://i.imgur.com/Htt4oIK.jpg is what I currently have for most of my blocks. One line for title (blue), one line for content (green). Dark green is the general "row" and red are the "blocks". The code for this layout is the following:

fluidRow(
    column(4, wellPanel()),
    column(2, mainPanel(
        p("blue"),
        p("green")
    )),
    column(2, mainPanel()),
    column(2, mainPanel()),
    column(2, mainPanel())
)

Now, that:

https://i.imgur.com/i728blL.jpg is what I am trying to achieve, and I have not been able to reach that result yet. I have tried a couple of things:

1) Using a different fluidRow for the title and for the contents. The problem with that is the formatting, since the control box on the left is part of the first row, it is constraining the height of the row itself, meaning the header will be much higher than the contents. It looks like this: https://i.imgur.com/sU0AEds.jpg, and I want to cut down the useless space.

Syntax for that would be:

fluidRow(
    column(4, wellPanel()),
    column(8, mainPanel(
        p("blue")
    ))
),
fluidRow(
    column(4, mainPanel()),
    column(2, mainPanel(
        p("green")
    )),
    column(2, mainPanel()),
    column(2, mainPanel()),
    column(2, mainPanel())
)

2) Nestling the sub-blocks within a larger column. The code for that would be like this:

fluidRow(
    column(4, wellPanel()),
    column(8, mainPanel(
        p("blue"),
        column(2, mainPanel(
            p("green")
        )),
        column(2, mainPanel()),
        column(2, mainPanel()),
        column(2, mainPanel())
    ))
)

And the problem with that is that, somehow, columns within columns seem not to be behaving properly. Instead of having the width 2 columns occupying the whole space of my width 8 columns, they end up having a weird width and overlapping each other.

Ideas? There might be an easy HMTL solution but I'm really not an expert in that. Thank you!

1
Welcome to SO. It it better to embed your images in your post instead of adding them as links. meta.stackoverflow.com/questions/303812/… Thanks!Gene Z. Ragan

1 Answers

0
votes

You could split the second column into four columns of width 3. Placing these columns inside fluidRow will also align them to the title element above.


EDIT

Dynamically generated columns and boxes. Set the width of the box as ceiling(12 / number of boxes). When the sum of widths exceeds 12, the boxes overflow in second row. We have to use something like ceiling or floor because fractions are not allowed in the bootstrap system, and when width is, e.g., 1.5, the boxes inherit the width of the parent column. An option is to set the maximum box width to 3 and have a two-row layout when the user selects > 4 boxes.

enter image description here


Code:

library(shiny)

wp <- tagList(wellPanel(
  h3("Title"),
  p(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
  )
))

ui <- fluidPage(fluidRow(
  column(
    width = 4,
    wp,
    sliderInput(
      "n_boxes",
      label = "Number of boxes",
      min = 1,
      max = 8,
      value = 2,
      step = 1
    )
  ),
  column(width = 8,
         wellPanel(h2("T I T L E")),
         uiOutput("blocks"))
))

server <- function(input, output) {
  make_boxes <- reactive({
    box_width <- ceiling(12 / input$n_boxes)
    message(box_width)

    x <-
      lapply(1:input$n_boxes, function(x)
        column(width = box_width, wp))
    x
  })

  output$blocks <- renderUI({
    fluidRow(make_boxes())
  })
}

shinyApp(ui, server)

For a potential alternative approach that allows with of the column to exceed 12 and uses a horizontal scrollbar, have a look at this thread: R shiny Dashboard : Exceed the bootstrap width = 12 and add an horizontal scrollbar