简体   繁体   中英

R Shiny Flexdashboard ValueBox in Column layout

I need to align some elements in a column layout in a Shinydashboard which combines some elements from flexdashboard. Here's the code:

library(shiny)
library(shinydashboard)
library(flexdashboard)

ui <- dashboardPage(
  dashboardHeader(title = "Dashboard"),
  dashboardSidebar(),
  dashboardBody(
    column(3,flexdashboard::valueBoxOutput("ValueBox")),
    #flexdashboard::valueBoxOutput("ValueBox"),
    column(3,plotOutput("plot1",height = 150)),
    column(6,h3("Gauges"),
           fluidRow(
             column(3,flexdashboard::gaugeOutput("Gauge1")),
             column(3,flexdashboard::gaugeOutput("Gauge2"))
             )
           )
    )
)

server <- function(input, output) {

  output$ValueBox <- renderValueBox({
    shinydashboard::valueBox(
      value = 100,
      subtitle = "Value",
      icon = icon("area-chart"),
      color = "aqua"
    )
  })

  set.seed(122)
  histdata <- rnorm(500)

  output$plot1 <- renderPlot({
    data <- histdata
    hist(data)
  })

  output$Gauge1 <- flexdashboard::renderGauge({
    gauge(60, min = 0, max = 100, symbol = "%") 
  })  

  output$Gauge2 <- flexdashboard::renderGauge({
    gauge(25, min = 0, max = 100, symbol = "%") 
  })    
}

shinyApp(ui, server)

This produces the output where the value box only fills approximately a third of the space designed for it: 在此处输入图片说明

When I change the valueBoxOutput to be outside of a column (comment out the first and uncomment the second line in the dashboardBody ), the valuebox does fill the full allocated space, but the "Gauge" output is forced on another line rather than to the right: 在此处输入图片说明

How do I force the "combination" of the two approaches so that the result looks something like this? 在此处输入图片说明

I have tried the following without success:

  • Use the shinydashboard::valueBoxOutput instead
  • Utilize the width argument of column as well as valueBoxOutput commands

After experimenting with column widths based on ismirsehregal's answer, I have discovered what the issue was.

The UI part is correct and both ways are capable of producing the result. The issue was that the definition inside renderValueBox did not specify the width argument, which was by default set to 4 and represents the relative width compared to the parental environment. Thus, in the first case, the box takes 4/12 of the column of width 3. In the second case, the output had a width of 4+3+6=13, which is higher than 12 and hence was broken into two lines.

The following definition solves the problem:

  output$ValueBox <- renderValueBox({
    shinydashboard::valueBox(
      value = 100,
      subtitle = "Value",
      icon = icon("area-chart"),
      color = "aqua",
      width = 12
    )
  })

The width = 12 sets the box to fill out the whole width of the parental environment, which in this case is a column of width 3. One can also use width = 3 directly and drop out the column definition, but the first way is preferred as the width of all three elements is specified in the UI rather than the server.

This works for me:

在此处输入图片说明

library(shiny)
library(shinydashboard)
library(flexdashboard)

ui <- dashboardPage(
  dashboardHeader(title = "Dashboard"),
  dashboardSidebar(),
  dashboardBody(
    flexdashboard::valueBoxOutput("ValueBox", width = "100%"), # Edit %
    #flexdashboard::valueBoxOutput("ValueBox"),
    column(4,plotOutput("plot1",height = 150)),
    column(4,h3("Gauges"),
           fluidRow(
             column(6,flexdashboard::gaugeOutput("Gauge1")),
             column(6,flexdashboard::gaugeOutput("Gauge2"))
           )
    )
  )
)

server <- function(input, output) {

  output$ValueBox <- renderValueBox({
    shinydashboard::valueBox(
      value = 100,
      subtitle = "Value",
      icon = icon("area-chart"),
      color = "aqua"
    )
  })

  set.seed(122)
  histdata <- rnorm(500)

  output$plot1 <- renderPlot({
    data <- histdata
    hist(data)
  })

  output$Gauge1 <- flexdashboard::renderGauge({
    gauge(60, min = 0, max = 100, symbol = "%") 
  })  

  output$Gauge2 <- flexdashboard::renderGauge({
    gauge(25, min = 0, max = 100, symbol = "%") 
  })    
}

shinyApp(ui, server)

So here is the preferred way based on Radek Janhuba's insights - setting the appropriate width while rendering (for everyone going here later):

library(shiny)
library(shinydashboard)
library(flexdashboard)

ui <- dashboardPage(
  dashboardHeader(title = "Dashboard"),
  dashboardSidebar(),
  dashboardBody(
    column(4,flexdashboard::valueBoxOutput("ValueBox")),
    column(4,plotOutput("plot1",height = 150)),
    column(4,h3("Gauges"),
           fluidRow(
             column(6,flexdashboard::gaugeOutput("Gauge1")),
             column(6,flexdashboard::gaugeOutput("Gauge2"))
           )
    )
  )
)

server <- function(input, output) {

  output$ValueBox <- renderValueBox({
    shinydashboard::valueBox(
      value = 100,
      subtitle = "Value",
      icon = icon("area-chart"),
      color = "aqua",
      width = 12
    )
  })

  set.seed(122)
  histdata <- rnorm(500)

  output$plot1 <- renderPlot({
    data <- histdata
    hist(data)
  })

  output$Gauge1 <- flexdashboard::renderGauge({
    gauge(60, min = 0, max = 100, symbol = "%") 
  })  

  output$Gauge2 <- flexdashboard::renderGauge({
    gauge(25, min = 0, max = 100, symbol = "%") 
  })    
}

shinyApp(ui, server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM