Search code examples
cssrshinyflexdashboard

Adjust layout of flexdashboard gauges in R shiny app?


I am trying to generate a grid of gauges in my shiny app, however I am unsure how to adjust the layout of the gauges I am generating. Here is a reprex of my app:

# import libraries
library(shiny)
library(flexdashboard)
library(purrr)
library(magrittr)

ui <- fluidPage(
  # add first gauge set to ui
  fluidRow(
    uiOutput("first_gauge")),
  # add second gauge set to ui
  fluidRow(
    uiOutput("second_gauge"))
)

server <- function(input, output){
  # create first set of gauges
  output$first_gauge <- renderUI({
    # create 4 values and dynamically create gauges
    1:4 %>%
      purrr::map(flexdashboard::gauge, min = 0, max = 10)
  })
  # create second set of gauges
  output$second_gauge <- renderUI({
    # create 4 values and dynamically create gauges
    5:8 %>%
      purrr::map(flexdashboard::gauge, min = 0, max = 10)
  })
}

# run shiny app
shinyApp(ui, server)

This app formats the 8 gauges in one long column like this:

gauge1
gauge2
gauge3
gauge4
gauge5
gauge6
gauge7
gauge8

But I am trying to format them in 2 rows of 4 like this:

gauge1 gauge2 gauge3 gauge4
gauge5 gauge6 gauge7 gauge8

I don't need the page to be fluid, it can be fixed. When I have tried messing with the column settings in fluidRow or fixedRow the gauges don't seem to move.

I have been experimenting with using includeCSS and messing with these margins, but I know little CSS and this doesn't seem to modify the margins between gauges:

.html-widget.gauge svg {
  height: 40%; 
  margin-top: 10px;
  margin-bottom: 10px;
}

Solution

  • use this

    # import libraries
    library(shiny)
    library(flexdashboard)
    library(purrr)
    library(magrittr)
    
    ui <- fluidPage(
        # add first gauge set to ui
        fluidRow(
            uiOutput("first_gauge")),
        # add second gauge set to ui
        fluidRow(
            uiOutput("second_gauge")),
        tags$style(".gauge.html-widget {display: inline-block;}"),
    )
    
    server <- function(input, output){
        # create first set of gauges
        output$first_gauge <- renderUI({
            # create 4 values and dynamically create gauges
            tagList(
                1:4 %>%
                    purrr::map(flexdashboard::gauge, min = 0, max = 10),
                tags$script("$('.gauge.html-widget').css({height: '100px', width: '22%'})")
            )
        })
        # create second set of gauges
        output$second_gauge <- renderUI({
            # create 4 values and dynamically create gauges
            tagList(
                5:8 %>%
                    purrr::map(flexdashboard::gauge, min = 0, max = 10),
                tags$script("$('.gauge.html-widget').css({height: '100px', width: '22%'})")
            )
        })
    }
    
    # run shiny app
    shinyApp(ui, server)
    
    • We first need to change the gauge display from block (default) to inline-block so they can be displayed in the same row. block means the current element take up all width of current row, so we need to change it. To change this, we can simply add a style tag.
    • Default flexdashboard::gauge takes a lot of height and width, however the R function doesn't provide us any argument to change the default height and width, and it uses style="xxx" for the CSS later on HTML, which has the highest priority. Adding style tag will not do the work. We need to use javascript change this. Since the gauge is dynamically rendered from server, the script also needs to be added on server.
    • To display 4 gauge per row, each one of them takes 25% of the width, but there is some padding added in the original style, so we can't use exact 25, must be smaller than this number. Here 22 is used, change it to a reasonable number you want. enter image description here